这道题还是很简单的,毕竟是NOI第一题。
首先不难发现可以使用二分图描述问题,问题化归到一个求二分图完备匹配的问题。
至于字典序最小,可以再匹配时,如果i可以与j或k匹配(j<k),则让i与j匹配。
【代码】
var
a:array[0..10000,0..5] of longint;
v:array[0..10000] of boolean;
link,match:array[0..10000] of longint;
i,j,k,m,n,t:longint;
procedure ins;
begin
if (j>=0)and(j<=n-1) then
begin
inc(m);a[i,m]:=j;
end;
end;
function find(x:longint):boolean;
var i:longint;
begin
for i:=1 to a[x,0] do
if not v[a[x,i]] then
begin
v[a[x,i]]:=true;
if (link[a[x,i]]=-1)or find(link[a[x,i]]) then
begin
link[a[x,i]]:=x;match[x]:=a[x,i];
exit(true);
end;
end;
exit(false);
end;
begin
assign(input,'transform9.in');reset(input);
assign(output,'transform.out');rewrite(output);
readln(n);
for i:=0 to n-1 do
begin
read(k);m:=0;
j:=i+k;ins;
j:=i-k;ins;
j:=n-k+i;ins;
j:=i-n+k;ins;
for j:=1 to m do
for k:=j+1 to m do
if a[i,j]>a[i,k] then
begin
t:=a[i,j];a[i,j]:=a[i,k];a[i,k]:=t;
end;
a[i,0]:=m;
end;
fillchar(link,sizeof(link),255);
for i:=n-1 downto 0 do
begin
fillchar(v,sizeof(v),0);
if not find(i) then
begin
writeln('No Answer');
halt;
end;
end;
for i:=0 to n-2 do
write(match[i],' ');
writeln(match[n-1]);
close(input);close(output);
end.
本文探讨了一道NOI初赛题目,通过将问题转化为二分图匹配问题,并采用字典序最小原则解决。代码实现简洁高效。

390

被折叠的 条评论
为什么被折叠?



