G2. Medium Demon Problem (hard version)

链接

题目链接

思路

拓扑排序。显然到仅剩下环的时候就稳定了。 原来的思路是采用逐层推进的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;
}
posted @ 2025-07-31 17:10  WHUStar  阅读(5)  评论(0)    收藏  举报