题意:n个人,每个人有一个目标人Ci(可以是自己),如果给定一个数t,指定从一个人x开始,那么x会传给Cx t-1,Cx会传给CCx t-2……
当a传给b 1时,b被称作Joon,求一个最小的t,使从任意一个人x开始传递t的情况下,最后Joon为y,那么从y出发传递t最后Joon为x
sol
把x传给Cx看成x到Cx有一条单向边,那么每个点出度为1,可以看出合法的情况是图只由环组成,所以处理出来所有的环,对于一个长度len为奇数的环,只能是转len回到自己。对于长度为偶数的环,可以先转len/2
然后最后再求个lcm就可以了,可以做到大概O(n),最坏情况下nlogn
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,C[200],tp,St[200],m,A[200]; bool vis[200]; int Gcd(int a,int b){ if (!b) return a; return Gcd(b,a%b); } int main(){ scanf("%d",&n); int i; for (i=1;i<=n;i++) scanf("%d",&C[i]); for (i=1;i<=n;i++) if (!vis[i]){ int cur=i; vis[i]=1; memset(St,0,sizeof(St)); tp=1; St[1]=i; while (1){ cur=C[cur]; if (!vis[cur]){ St[++tp]=cur; vis[cur]=1; continue; } if (cur!=St[1]){ cout<<-1; return 0; } m++; if (tp%2==0) A[m]=tp/2; else A[m]=tp; break; } } for (i=2;i<=m;i++){ int gcd=Gcd(A[i],A[i-1]); A[i]/=gcd; A[i-1]/=gcd; A[i]*=A[i-1]*gcd; } cout<<A[m]; }