题意
会给你一个有向图,你要找到最小的步数 t 如果u这个点走t步能到v,并且v这个点走t步能到u则满足要求,问对于所有的点一个共同满足得t最小是多少,如果没有答案输出-1。
思路
dfs跑环,自环不处理,如果一些点不能构成环,那么答案一定无解(因为是一个有向图如果不在环里上述条件一定不存在)然后我们再把每一个环得长度再判断长度是奇数还是偶数,偶数除以二,就是本身的长度,然后对每一个环所满足的t求一个最小公倍数(因为所有的点都要满足并且值最小)。
偶数的情况t = 长度/2;
奇数的话t就只能是环的长度。
代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long
using namespace std;
const int N = 2e5 + 10;
int h[N], idx, ans = 1;
bool f = 0, st[N];
vector<int> v;
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b)
{
return a * b / gcd(a, b);
}
struct node
{
int u, v;
}e[N];
void add(int u, int v)
{
e[++idx].v = v;
e[idx].u = h[u];
h[u] = idx;
}
void dfs(int u)
{
if (st[u])
{
f = 1;
int res = v.size();
if (v[0] != u) { cout << -1 << endl; exit(0); }
if (res % 2 == 0) res /= 2;
ans = lcm(ans, res);
return;
}
st[u] = 1;
v.push_back(u);
for (int i = h[u]; i; i = e[i].u)
{
int s = e[i].v;
dfs(s);
}
v.pop_back();
}
signed main()
{
IOS;
int n, m;
cin >> n;
m = n;
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
if (x == i) { m--; continue; }
add(i, x);
}
if (m == 0) { cout << 1 << endl; return 0;}
for (int i = 1; i <= n; i++)
{
if (!st[i]) dfs(i);
}
if (!f) ans = -1;
cout << ans << endl;
return 0;
}