题目: | 变换序列 | |
来源: | Noi 2009 day1 第一题 | |
题目大意: | 对于N个整数0,1,...,N-1,一个变换序列T可以将i变成Ti,其中Ti∈{0,1,...,N-1}且 。 U……(图片无法显示,请连接 题目来源)∀;x,y∈{0,1,...,N-1},定义x和y之间的 距离D(x,y)=min{|x-y|,N-|x-y|} 。给定每个i和 Ti之间的距离D(i,Ti),你需要求出一个满 足要求的变换序列T。如果有多个满足条件 的序列,输出其中字典序最小的一个。 | |
数据范围: | N≤10000 | |
样例: | 5 1 1 2 2 1 | 1 2 4 0 3 |
做题思路: | 刚看到题,从理解题以上就让我多次丧失信心,终于找到突破,询问了同学匈牙利算 法,然后在网上通过stall4(Usaco)习得此算法,发现这个题就是一个二分图求最 大匹配,好了,大头出来了就好做了 | |
知识点: | 二分图求最大匹配(匈牙利算法) |
var
a:array[0..10000,0..10000]of boolean;
b:array[0..10000]of boolean;
c:array[0..10000]of longint;
watch:array[0..10000]of longint;
n,m,y,i,k,j,ans:longint;
function path(x:longint):boolean;
var
i:longint;
begin
for i:=1 to n do
if (a[x,i])and(not b[i]) then
begin
b[i]:=true;
if (c[i]=0)or(path(c[i])) then
begin
c[i]:=x;
watch[x]:=i;{<记录对应序列的点,不断更新的,不要把它与c[]混了昂,c每次都要初始化的>}
exit(true);
end;
end;
exit(false);
end;
procedure hungary;
var
i:longint;
begin
fillchar(c,sizeof(c),0);
for i:=n downto 1 do
begin
fillchar(b,sizeof(b),false);
if not path(i) then
begin
writeln('No Answer');
halt;
end;
end;
end;
begin
assign(input,'transform.in');reset(input);
assign(output,'transform.out');rewrite(output);
fillchar(a,sizeof(a),false);
readln(n);
for i:=1 to n do
begin
read(y);
a[i,(i+y-1)mod n+1]:=true; {<向右距y的>}
a[i,(i-y+n-1)mod n+1]:=true;{<向左距y的>}
end;
ans:=0;
hungary;
for i:=1 to n-1 do write(watch[i]-1,' ');
writeln(watch[n]-1);{<貌似最好一个数字后不要空格,所以我谨慎的这么写了>}
close(input);close(output);
end.
题目来源:
http://www.rqnoj.cn/Problem_522.html