题意:n个人带着m类面具,其中第i类面具能看到第i % m +1类的面具,给定一些a能看见b的关系,问m的最大最小值,要求m满足m>=3
图论好题,作为一名蒟蒻我觉得考场上我就输出-1 -1 就可以了...(洛谷能得一个点)
推荐一个十分好的带图的题解:http://blog.csdn.net/qpswwww/article/details/44044229
这里简述一下分类讨论:
(一)存在环 (单独这一种情况,洛谷能过7个点)
求出每个环包括的点的个数,每个环一定能被正好拆成k个循环才能满足题意和已知,
所以此时的最大值为各个环大小的最大公约数,最小值当然就是最大公约数大于3的最小因子
当gcd小于3时无解
(二)没有环
此时最大值等于每个联通分量里最长链长度的累加(一开始naive的认为是取max后来才反应过来是去sum......)
由于没有环的限制(不用看回去),所以最小值当然就是3
当累加和小于3时无解
=======我是一本道和口胡的分界线_(:з」∠)_===========
下面开始口胡
原图中给出的关系建边权为1,同时建反边边权为-1,把有向边变成无向边,
因为当两个点同时指向一个点时,这三个点中有一个点是确定的那么这三个就是确定的,所以完全可以把它们三个缩成一个点,解决了链之间的限制关系(具体参见上面推荐的博客)
在实现中我们同样先判断是否有环,有的话就按照第一种处理没有的话再按照第二种处理
对于判断是否有环和同时更新答案,利用dfs,每找到一个环就求一下gcd(注意是绝对值),如果最后gcd不是0那么说明有环
对于求出每个联通分量里最长链的长度,如果我们访问到了一个已经访问过的点p 那么 max{d[x]+len[q]-d[p]} (d[x]表示x到该链第一个dfs的点的距离(“缩点”以后的))
我并不知道我在说什么,但是 把有向边转化成无向边(强制成环)的思想 和 这道题性质(能看见的条件) ,二者结合的还是十分巧妙的(不得不跪)
var
n,m,a,b,ans,l :longint;
i :longint;
maxn,minn :longint;
vis :array[0..100010] of boolean;
d,num,last :array[0..100010] of longint;
pre,other,len :array[0..2000010] of longint;
function gcd(a,b:longint):longint;
begin
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 dfs1(x:longint);
var
p,q:longint;
begin
vis[x]:=true;
q:=last[x];
while q<>0 do
begin
p:=other[q];
if not vis[p] then
begin
num[p]:=num[x]+len[q];
dfs1(p);
end else ans:=gcd(ans,abs(num[x]+len[q]-num[p]));
q:=pre[q];
end;
end;
procedure dfs2(x:longint);
var
p,q:longint;
begin
vis[x]:=true;
if d[x]>maxn then maxn:=d[x];
if d[x]<minn then minn:=d[x];
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis[p] then
begin
d[p]:=d[x]+len[q];
dfs2(p);
end;
q:=pre[q];
end;
end;
begin
read(n,m);
for i:=1 to m do
begin
read(a,b);
connect(a,b,1);
connect(b,a,-1);
end;
//
for i:=1 to n do if not vis[i] then dfs1(i);
if (ans<>0) then
begin
if ans<3 then writeln(-1,' ',-1) else
begin
for i:=3 to ans do
if ans mod i=0 then break;
writeln(ans,' ',i);
end;
exit;
end;
//
fillchar(vis,sizeof(vis),false);
for i:=1 to n do
if not vis[i] then
begin
maxn:=0; minn:=0;
dfs2(i);
inc(ans,maxn-minn+1);
end;
if ans<3 then writeln(-1,' ',-1)
else writeln(ans,' ',3);
end.
——by Eirlys