题目
题解
可以把整个图分为环和链来考虑。
对于链的情况, 的最小值就是链的长度,最大值就是所有的链接起来。
对于环的情况, 的最大值就是环的大小,环大小的约数k也可以取。
现在问题就变成了怎样求环。如果是无向图的话,直接随便找个点 就行了。但是现在是有向图,所以需要变成无向图。将原图中的每一条边加上一个 的权值,然后再新建一条权值是 的反向边就行了。
#include<bits/stdc++.h>
using namespace std;
const int N=100002;
struct node{
int to,ne,w;
}e[20*N];
int h[N],dis[N],mx[N],mn[N],ans1,ans2,u,v,i,f[N],tot,fl[N],n,m,rx,ry,now;
inline char gc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
return x*fl;
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
void add(int x,int y,int z){
e[++tot]=(node){y,h[x],z};
h[x]=tot;
}
void dfs(int u){
fl[u]=0;
mx[now]=max(mx[now],dis[u]);
mn[now]=min(mn[now],dis[u]);
for (int i=h[u],v;i;i=e[i].ne)
if (fl[v=e[i].to]){
dis[v]=dis[u]+e[i].w;
dfs(v);
}else ans1=__gcd(ans1,abs(dis[u]+e[i].w-dis[v]));
}
int main(){
n=read();m=read();
for (i=1;i<=n;i++) f[i]=i;
for (i=1;i<=m;i++){
u=read(),v=read();
add(u,v,1);add(v,u,-1);
rx=find(u);ry=find(v);
if (rx!=ry) f[rx]=ry;
}
memset(fl,1,sizeof(fl));
memset(mn,63,sizeof(mn));
for (i=1;i<=n;i++)
if (fl[i]) now=find(i),dfs(i);
for (i=3;i<=ans1 && !ans2;i++)//环
if (!(ans1%i)) ans2=i;
if (!ans1){//链
ans2=3;
for (i=1;i<=n;i++)
if (f[i]==i) ans1+=mx[i]-mn[i]+1;
}
if (ans1<3) ans1=ans2=-1;
printf("%d %d",ans1,ans2);
}