http://codeforces.com/contest/742/problem/C
首先把图建起来。
对于每个a[i],那么就在i --- a[i]建一条边,单向的。
如果有一个点的入度是0或者是>= 2,那么就不行了。直接-1
然后就是把图分成若干个圈了。
对于每一个圈,只需要找一个点,dfs,算出它回到自己的时候需要多少步数。
如果步数是偶数,那么只需要取中点,x -- mid 然后mid -- x步数是一样,那么最小的t就是长度/2
如果是奇数,那没办法了。
然后把所有的圈的步数来一个lcm,就是答案。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <assert.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 1e2 + 20; int e[maxn][maxn]; int in[maxn]; bool vis[maxn]; int tans, ans; int n; int lcm(int a, int b) { return a / __gcd(a, b) * b; } void dfs(int cur, int haha) { for (int i = 1; i <= n; ++i) { if (e[cur][i] == 1 && vis[i] == false) { vis[i] = true; tans++; dfs(i, haha); } } } void work() { ans = 1; memset(e, 0x3f, sizeof e); IOS; cin >> n; for (int i = 1; i <= n; ++i) { int x; cin >> x; e[i][x] = 1; in[x]++; } for (int i = 1; i <= n; ++i) { if (in[i] == 0 || in[i] >= 2) { cout << -1 << endl; return; } } for (int i = 1; i <= n; ++i) { if (vis[i]) continue; tans = 0; dfs(i, i); if (tans % 2 == 0) tans /= 2; ans = lcm(ans, tans); } cout << ans << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif work(); return 0; }