noip2005篝火晚会 2008.10.18
注意:
1. 刚开始,我用的是图来标记这两个人是否已经输出过,一直出错,后来看了标称,方法很好
2. 求出序列后,因为是圆环,要正着求一次差,求相同的最大值,还要倒着求一次差,求最大值,这样才圆满,我只正着求了,故一直出错
3. 不能用abs,若剪出的结果是负数,应加上n;标称的处理方法很好,相减后+n,再mod n
Program:
program noip2005_3;
const
maxn=50000;
var
n:longint;
tm,w:array[0..maxn] of longint;
g:array[1..maxn,0..4] of longint;
function solve(x,y:longint):boolean;
var
i:integer;
begin
solve:=true;
for i:=1 to g[x,0] do
if y=g[x,i]
then exit(false);
end;{判断两个人以前是否出现过}
procedure init;
var
i,x,y:longint;
begin
readln(n);
for i:=1 to n do
begin
read(x,y);
if solve(i,x)
then begin
inc(g[x,0]); g[x,g[x,0]]:=i;
inc(g[i,0]); g[i,g[i,0]]:=x
end;
if solve(i,y)
then begin
inc(g[y,0]); g[y,g[y,0]]:=i;
inc(g[i,0]); g[i,g[i,0]]:=y;
end;
if (g[x,0]>2) or (g[y,0]>2)
then begin
writeln(-1); close(input); close(output);
halt
end;{不必读完,出现问题,不再读他,就跳出}
end;
end;
procedure ready;
var
i,j:longint;
begin
tm[0]:=0; tm[1]:=1;
for i:=2 to n do
for j:=1 to g[tm[i-1],0] do
if g[tm[i-1],j]<>tm[i-2]
then tm[i]:=g[tm[i-1],j];
end;
procedure main;
var
i,j,max,ans:longint;
begin
max:=0;
for i:=1 to n do
inc(w[ (tm[i]+n-i) mod n ]);
for i:=0 to n-1 do
if w[i]>max then max:=w[i];
fillchar(w,sizeof(w),0);
for i:=n downto 1 do
inc(w[ (tm[i]+n-(n-i+1)) mod n ]);
for i:=0 to n-1 do
if w[i]>max then max:=w[i];
ans:=n-max;
writeln(ans);
end;
begin
assign(input,'fire.in');
assign(output,'fire.out');
reset(input); rewrite(output);
init;
ready;
main;
close(input); close(output);
end.