很巧妙的题

首先有几种情况

1. 有环 2.两点间有多条路径 3.其他

3.显然最简单,最小是3,最大是每个弱联通块中最长链

2.显然,两点间两条路径的差是答案的倍数

1.出现环,那答案一定是其约数,那么最大答案就是所有环长的最大公约数,最小是最大的大于等于3的最小因数

综合以上,我们就有了大概的思路,但是不好处理

有一个精妙的做法,对于每条边添加一个长度为-1的反向边,一下就简单多了

  1 type node=record
  2        po,next,num:longint;
  3      end;
  4 
  5 var e:array[0..4000010] of node;
  6     p,d:array[0..200010] of longint;
  7     v:array[0..200010] of boolean;
  8     mi,i,l,r,n,m,len,ans,x,y:longint;
  9 
 10 function min(a,b:longint):longint;
 11   begin
 12     if a>b then exit(b) else exit(a);
 13   end;
 14 
 15 function max(a,b:longint):longint;
 16   begin
 17     if a>b then exit(a) else exit(b);
 18   end;
 19 
 20 function gcd(a,b:longint):longint;
 21   begin
 22     if b=0 then exit(a)
 23     else exit(gcd(b,a mod b));
 24   end;
 25 
 26 procedure add(x,y,z:longint);
 27   begin
 28     inc(len);
 29     e[len].po:=y;
 30     e[len].num:=z;
 31     e[len].next:=p[x];
 32     p[x]:=len;
 33   end;
 34 
 35 procedure dfs(x:longint);
 36   var i,y:longint;
 37   begin
 38     v[x]:=true;
 39     i:=p[x];
 40     while i<>-1 do
 41     begin
 42       y:=e[i].po;
 43       if v[y] then ans:=gcd(ans,abs(d[x]+e[i].num-d[y]))
 44       else begin
 45         d[y]:=d[x]+e[i].num;
 46         dfs(y);
 47       end;
 48       i:=e[i].next;
 49     end;
 50   end;
 51 
 52 procedure find(x:longint);
 53   var i,y:longint;
 54   begin
 55     v[x]:=true;
 56     l:=min(l,d[x]);
 57     r:=max(r,d[x]);
 58     i:=p[x];
 59     while i<>-1 do
 60     begin
 61       y:=e[i].po;
 62       if not v[y] then
 63       begin
 64         d[y]:=d[x]+e[i].num;
 65         find(y);
 66       end;
 67       i:=e[i].next;
 68     end;
 69   end;
 70 
 71 begin
 72   len:=-1;
 73   fillchar(p,sizeof(p),255);
 74   readln(n,m);
 75   for i:=1 to m do
 76   begin
 77     readln(x,y);
 78     add(x,y,1);
 79     add(y,x,-1);
 80   end;
 81   for i:=1 to n do
 82     if not v[i] then dfs(i);
 83   if ans<>0 then
 84   begin
 85     mi:=ans;
 86     for i:=3 to ans do
 87       if ans mod i=0 then
 88       begin
 89         mi:=i;
 90         break;
 91       end;
 92   end
 93   else begin
 94     fillchar(v,sizeof(v),false);
 95     for i:=1 to n do
 96       if not v[i] then
 97       begin
 98         d[i]:=0;
 99         l:=0;  r:=0;
100         find(i);
101         ans:=ans+r-l+1;
102       end;
103 
104     mi:=3;
105   end;
106   if ans<3 then writeln('-1 -1') else writeln(ans,' ',mi);
107 end.
View Code

 

posted on 2015-06-20 15:49  acphile  阅读(148)  评论(0编辑  收藏  举报