很巧妙的题
首先有几种情况
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.
时间: 2024-11-07 07:42:54