C. Arpa's loud Owf and Mehrdad's evil plan DFS + LCM

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;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6139930.html