【题目描述】有n个点和m条关系。只有集合i的点才会和集合i+1的点连边,特别的集合k的点可以和集合1连边(构成一个蛇咬尾的环形)。给定的关系和点之后,问k的最小值最大值是多少。(约定k≥3)
【分析】只有环会对集合产生约束性,(链可以困成一卷一卷的)。所有环的最小公因数(最小周期,小环转1圈,大环转n圈)就是k的最大值。最小值就是k≥3的最小约数。如果最小公因数(周期)小于3,那么信息有误,输出“-1 -1”。
【code】
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define f first
#define s second
using namespace std;
const int maxn=1e5+1000;
struct wtfd{
int bh;
vector<int>zb,fb;
}d[maxn];
int n,m;
int ans;
int lc[3];
bool alr[maxn];
pair<int,int>b[maxn*10];
inline void read(int &x){
x=0;char tmp=getchar();
while(tmp<'0'||tmp>'9') tmp=getchar();
while(tmp>='0'&&tmp<='9') x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
}
int gcd(int a,int b){
if (b==0) return a;
else return gcd(b,a%b);
}
void dfs(int dq,int bh){
if (!alr[dq]){
alr[dq]=true;
d[dq].bh=bh;
lc[1]=std::min(lc[1],bh);
lc[2]=std::max(lc[2],bh);
for(unsigned int i=0;i<d[dq].zb.size();++i)
dfs(d[dq].zb[i],bh+1);
for(unsigned int i=0;i<d[dq].fb.size();++i)
dfs(d[dq].fb[i],bh-1);
}
else ans=gcd(ans,abs(bh-d[dq].bh));
}
int main(){
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
cin>>n>>m;
for (int i=0;i<m;++i)
read(b[i].f),read(b[i].s);
sort(b,b+m);
d[b[0].f].zb.push_back(b[0].s);
d[b[0].s].fb.push_back(b[0].f);
for(int i=1;i<m;++i){
if(b[i].s!=b[i-1].s||b[i].f!=b[i-1].f){
d[b[i].f].zb.push_back(b[i].s);
d[b[i].s].fb.push_back(b[i].f);
}
}
for(int i=1;i<=n;++i)
if(!alr[i]){
dfs(i,0);
lc[0]+=lc[2]-lc[1]+1;
lc[1]=lc[2]=0;
}
if(ans>=3){
for(int i=3;i<=ans/2;++i)
if(ans%i==0){
cout<<ans<<' '<<i<<endl;
return 0;
}
cout<<ans<<' '<<ans<<endl;
return 0;
}
if (ans==0&&lc[0]>=3){
cout<<lc[0]<<' '<<3<<endl;
return 0;
}
printf("-1 -1\n");
}