[NOI2008] 假面舞会
考虑到有环的情况下最大值就是所有环长的最大公约数,最小值就是最小公约数。
无环则是所有最长链的和,以及\(3\)。
无法得到答案的情况特殊判断。
本题是在有向图里找环和最长链的一个经典做法。
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#define ll long long
#define N 100005
struct P{int to,v;P(int x = 0,int y = 0){to = x,v = y;v = 0;}};
std::vector<P>QWQ[N];
ll n,m;
ll maxn,minn,ans,res;
inline ll gcd(ll a,ll b){return (a == 0) ? b : gcd(b % a,a);}
ll dis[N];
bool vis[N];
inline void dfs(int u,ll s){
if(vis[u]){
ans = gcd(ans,abs(s - dis[u]));
return ;
}
dis[u] = s;
vis[u] = 1;
maxn = std::max(maxn,dis[u]);
minn = std::min(minn,dis[u]);
for(int i = 0;i < QWQ[u].size();++i){
int v = QWQ[u][i].to;
dfs(v,dis[u] + QWQ[u][i].v);
}
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i = 1;i <= m;++i){
ll x,y;
scanf("%lld%lld",&x,&y);
P a;
a.to = y,a.v = 1;
QWQ[x].push_back(a);
a.to = x,a.v = -1;
QWQ[y].push_back(a);
}
for(int i = 1;i <= n;++i)
if(!vis[i]){
maxn = -1e18,minn = 1e18;
dfs(i,1);
res = res + maxn - minn + 1;
}
if(ans){
if(ans < 3){
puts("-1 -1");
return 0;
}
for(int i = 3;i <= ans;++i)
if(ans % i == 0){
std::cout<<ans<<" "<<i<<std::endl;
return 0;
}
}
if(res < 3){
puts("-1 -1");
return 0;
}
std::cout<<res<<" "<<3<<std::endl;
}