noip2005篝火晚会 2008.10.18

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.


你可能感兴趣的:(NOIP)