Link with Limit
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 415 Accepted Submission(s): 129
Problem Description
Link has a function f(x), where x and f(x) are both integers in [1,n].
Let fn(x)=f(fn−1(x)) and f1(x)=f(x), he define the power of a number x as:
g(x)=limn→+∞1n∑i=1nfi(x)
He wants to know whether x has the same power for all x∈[1,n].
Input
The input consists of multiple test cases.
The first line contains an integer T (1≤T≤100) – the number of test cases.
For each test case:
In the first line, there is an integer n (1≤n≤105).
In the second line, there are n integers, the i-th integer shows the value of f(i) (1≤f(i)≤n).
It is guaranteed that the sum of n over all test cases will not exceed 106.
Output
For each test case, output ‘YES’ if all x have the same power. Otherwise, output ‘NO’.
Sample Input
2
2
1 2
2
1 1
Sample Output
NO
YES
题意大致为求出每个环的平均点权(有向图,每个点只有一条出边)
拓扑排序依次去掉所有入度为零的点,剩下的点会组成环,易知此题环与环之间不相交,求一遍即可
#include <bits/stdc++.h>
typedef long long ll;
const ll N = 100100;
const ll mod = (ll)1e9 + 7;
using namespace std;
ll in[N];
ll a[N];
ll n;
ll ans[N], tot;
void solve() {
scanf("%d", &n);
for (ll i = 0; i <= n; i++) in[i] = 0;
for (ll i = 1; i <= n; i++) {
scanf("%d", &a[i]);
in[a[i]]++;
}
queue<ll> que;
for (ll i = 1; i <= n; i++)
if (in[i] == 0) que.push(i);
ll u;
while (!que.empty()) {
u = que.front();
que.pop();
in[a[u]]--;
if (in[a[u]] == 0) que.push(a[u]);
}
ll p = -1, q = -1, flag = 0;
ll sum, cnt;
for (ll i = 1; i <= n; i++) {
if (in[i] == 0) continue;
sum = cnt = 0;
for (ll j = i; in[j]; j = a[j]) {
in[j] = 0;
sum += j;
cnt++;
}
if (p == -1 && q == -1) {
p = sum, q = cnt;
} else {
if (p * cnt != q * sum) {
flag = 1;
break;
}
}
}
if (flag)
printf("NO\n");
else
printf("YES\n");
}
int main() {
ll t = 1;
scanf("%d", &t);
while (t--) solve();
return 0;
}