Jeanny
寂兮,寥兮,独立不改,周行而不殆

小海酷爱数学,他的梦想是在太平洋上建立一个数学王国。

终于有一天,他的同学小升研发出了一类叫做“数学分子”的东西,并兴高采烈地跑来找到他,给了他 $N$ 种“数学分子”,按 $1$ 到 $N$ 依次编号。小海要用部分“数学分子”投放到太平洋上构建数学王国。

已知每种“数学分子”都可以掌控另一种“数学分子”。小海希望他能够掌控整个数学王国,因此,他希望 **所有被投放的“数学分子”都有至少一个没有被投放的“数学分子”能掌控它**。

小海想知道,**最多**可以投放的“数学分子”的种类数目。

1.第一个特征,发现每一个点只可能有一个出边。 图形一定有大于等于一个的简单环。

2.通过找规律发现,链上的点黑白染色即可。环上和链上的连接处,如果是被管的点,则相当于把环断开了。如果是管别人的点,也可能作为被管的点。因此,最终成为一个完整的环。

 

//一个特性:
//被管理的点,一定不用进栈。进栈的点,是管别人的.管别人的和被管的都要打标记。
//其余没有打过标记的一定是不相交的环。

#include <bits/stdc++.h>
using namespace std;
stack<int> q;
int to[1000005], ru[1000005], n, cnt, b[1000005], tot;
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> to[i];
        ru[to[i]]++;
    }
    for (int i = 1; i <= n; i++) {
        if (ru[i] == 0)
            q.push(i), b[i] = 1;
    }
    //将边砍掉
    while (!q.empty()) {
        int u = q.top();
        q.pop();
        int v = to[u];
        if (b[v] == 0) {
            cnt++;
            b[v] = 1;  //被管的打标记
            ru[to[v]]--;
            if (ru[to[v]] == 0)
                q.push(to[v]), b[to[v]] = 1;  //管别人的打标记
        }
    }
    //接下来只可能是不相交的环
    for (int i = 1; i <= n; i++) {
        if (b[i] == 0) {
            int v = to[i], tot = 1;  //还有一种自环
            b[i] = 1;
            while (v != i) {
                b[v] = 1;
                tot++;
                v = to[v];
            }
            cnt += tot / 2;
        }
    }
    cout << cnt << endl;

    return 0;
}

/*
12
4 4 4 5 6 8 5 9 10 11 8 11

12
4 4 4 5 8 12 5 9 10 11 8 11
*/

 


 

posted on 2024-09-14 16:56  Jeanny  阅读(19)  评论(0)    收藏  举报