链接
题目链接
思路
拓扑排序。显然到仅剩下环的时候就稳定了。
原来的思路是采用逐层推进的priority_queue做法,但是有点麻烦。所以采用了先找到环,再用环环外点的最大sum值为答案加2即可,如果没有那么就是2.
代码
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define tin long long
#define itn long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 2e5 + 10;
itn r[N];
int n;
itn rd[N], rdf[N];
itn num[N];
bool isa[N];
struct ele {
itn id, val;
ele(itn id, int val) {
this->id = id;
this->val = val;
}
bool operator<(ele x)const {
return x.val > val;
}
};
void solve()
{
cin >> n;
for (itn i = 1; i <= n; i++)rd[i]=rdf[i] =isa[i]= 0, num[i] = 1;
for (int i = 1; i <= n; i++) { cin >> r[i]; rd[r[i]]++; rdf[r[i]]++; }
int t = 1;
queue<int>q;
for (itn i = 1; i <= n; i++) { if (rd[i] == 0)q.push(i); }
while (!q.empty()) {
int now = q.front(); q.pop();
rdf[r[now]]--;
if (rdf[r[now]] == 0)q.push(r[now]);
}
for (itn i = 1; i <= n; i++)
if (rdf[i])
isa[i] = true;
int minn = 0;
for (itn i = 1; i <= n; i++) { if (rd[i] == 0)q.push(i); }
while(!q.empty()) {
int now = q.front(); q.pop();
if (isa[r[now]]) {
minn = max(minn, num[now]);
continue;
}
rd[r[now]]--;
num[r[now]] += num[now];
if (rd[r[now]] == 0)q.push(r[now]);
}
cout << minn + 2 << '\n';
}
signed main() {
IOS;
/**/int t;
cin >> t;
while (t--)
solve();
return 0;
}