Codeforces 741A:Arpa's loud Owf and Mehrdad's evil plan(LCM+思维)
http://codeforces.com/problemset/problem/741/A
题意:有N个人,第 i 个人有一个 a[i],意味着第 i 个人可以打电话给第 a[i] 个人,所以如果第 i 个人打电话出去,那么序列是 a[i], a[a[i]], a[a[a[i]]]……,打了 t 次电话后终点为y,那么从 y 也要打 t 次电话之后终点为 i,问最少要打多少次电话才能让所有人满足这样的条件。不存在输出 -1.
思路:这样的一个个序列就是一个环,因为要让所有人满足这个条件,所以 x * m = t , x 是每一个环节自身的长度, m 是一个整数, t 是最后的答案,那么求出所有环的最小公倍数,就是最后的答案了。如果环的长度为偶数,那么存在着一个 y 可以使得 x 能打电话给 y 的同时, y 也能打电话给 x,所以这样长度可以除以2。判断存不存在的话,只有每一个点的入度都不为 0,它才有可能形成环,否则会不能形成环。
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 using namespace std; 10 #define INF 0x3f3f3f3f 11 #define N 100010 12 typedef long long LL; 13 int deg[110]; 14 int a[110]; 15 16 LL solve(int n) { 17 LL ans = 1; 18 memset(deg, 0, sizeof(deg)); 19 for(int i = 1; i <= n; i++) { 20 if(deg[i] == 0) { // 经过的点的路径形成一个环 21 LL tmp = 1; 22 int x = a[i]; 23 deg[i] = 1; 24 while(!deg[x]) { 25 deg[x] = 1; 26 x = a[x]; 27 tmp++; 28 } 29 ans = ans / __gcd(ans, tmp) * tmp; 30 } 31 } 32 if(!(ans & 1)) ans /= 2; 33 return ans; 34 } 35 36 int main() 37 { 38 int n; 39 scanf("%d", &n); 40 for(int i = 1; i <= n; i++) { 41 scanf("%d", a+i); 42 deg[a[i]]++; 43 } 44 bool flag = true; 45 for(int i = 1; i <= n; i++) { 46 if(!deg[i]) { 47 flag = false; 48 break; 49 } 50 } 51 if(!flag) puts("-1"); 52 else printf("%I64d\n", solve(n)); 53 return 0; 54 }