W15 CF741A

题意: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];
}

猜你喜欢

转载自www.cnblogs.com/Pedestrian6/p/9201218.html
今日推荐