bzoj 1064 图论
我们根据能否看见建图,有向图边权设成1,然后我们转成无向图,
对于每条有向边连一条反边,边权是-1,然后从每个块中任意一个点开始
dfs,每个点有一个值,经过一条边到另一个点之后,用原来的点值和边权
更新新的点的点值,那么如果我们访问到了一个原来已经走过的点,那么我们
找到了一个环(可能是非环,就是一个点出两条有向边,然后又交在一点了),由于
数据是合法的,所以这样的非环的现在应该更新成的点值和原有的点值相等,如果不相等
的话,取差值的绝对值,就是这个环的长度。
那么我们对于所有块,每个块的环的长度都是种类数的倍数,所以取gcd就好了
还有一种情况就是没有环,全都是以链的形式存在的,对于这种形式,我们每个块
染色,然后找到每个块中点值最大的最小的差值就是最长链的长度。
无解的情况比较容易讨论,在此不再赘述。
/************************************************************** Problem: 1064 User: BLADEVIL Language: Pascal Result: Accepted Time:284 ms Memory:34596 kb ****************************************************************/ {$M 65536000} //By BLADEVIL var n, m :longint; pre, other, len :array[0..2000020] of longint; last :array[0..100010] of longint; l :longint; flag :array[0..100010] of boolean; size, father, key, tmin, tmax :array[0..100010] of longint; g :array[0..2000100] of longint; ans1, ans2 :longint; procedure swap(var a,b:longint); var c :longint; begin c:=a; a:=b; b:=c; end; function min(a,b:longint):longint; begin if a>b then min:=b else min:=a; end; function max(a,b:longint):longint; begin if a>b then max:=a else max:=b; end; function gcd(a,b:longint):longint; begin if b>a then swap(a,b); if b=0 then exit(a) else exit(gcd(b,a mod b)); end; procedure connect(x,y,z:longint); begin inc(l); pre[l]:=last[x]; last[x]:=l; other[l]:=y; len[l]:=z; end; procedure dfs(x:longint); var q, p :longint; begin flag[x]:=true; q:=last[x]; while q<>0 do begin p:=other[q]; if len[q]=1 then father[p]:=x; if not flag[p] then begin flag[p]:=true; size[p]:=size[x]+len[q]; key[p]:=key[x]; dfs(p); end else begin inc(g[0]); g[g[0]]:=abs(size[x]+len[q]-size[p]); if g[g[0]]=0 then dec(g[0]); end; q:=pre[q]; end; end; procedure init; var i :longint; x, y :longint; begin read(n,m); for i:=1 to m do begin read(x,y); connect(x,y,1); connect(y,x,-1); end; for i:=1 to n do father[i]:=-1; for i:=1 to n do if not flag[i] then dfs(i); end; procedure main; var i :longint; begin if g[0]=0 then begin fillchar(flag,sizeof(flag),false); for i:=1 to n do if (father[i]=-1) and (key[i]=0) then begin key[i]:=i; dfs(i); end; for i:=1 to n do tmax[i]:=-maxlongint; for i:=1 to n do tmin[i]:=maxlongint; for i:=1 to n do begin tmax[key[i]]:=max(tmax[key[i]],size[i]); tmin[key[i]]:=min(tmin[key[i]],size[i]); end; for i:=1 to n do if tmin[i]<>maxlongint then inc(ans1,tmax[i]-tmin[i]+1); if ans1<3 then begin writeln(-1,' ',-1); exit; end else begin writeln(ans1,' ',3); exit; end; end else begin ans1:=g[1]; for i:=2 to g[0] do ans1:=gcd(ans1,g[i]); if ans1<3 then begin writeln(-1,' ',-1); exit; end else begin ans2:=0; for i:=3 to ans1 do if ans1 mod i=0 then begin ans2:=i; break; end; if ans2=0 then ans2:=ans1; writeln(ans1,' ',ans2); end; end; end; begin init; main; end.