P4089 [USACO17DEC] The Bovine Shuffle S

P4089 [USACO17DEC] The Bovine Shuffle S

题目描述

Farmer John 坚信快乐的奶牛能产更多的奶,因此他在谷仓里安装了一个巨大的迪斯科球,并计划教他的奶牛跳舞!

在查阅了流行的奶牛舞蹈后,Farmer John 决定教他的奶牛“Bovine Shuffle”。Bovine Shuffle 包括他的 NNN 头奶牛(1≤N≤100,0001 \leq N \leq 100,0001N100,000)以某种顺序排成一行,然后进行连续的“洗牌”,每次洗牌可能会重新排列奶牛的顺序。为了让奶牛更容易找到自己的位置,Farmer John 为他的奶牛队伍标记了位置 1…N1 \ldots N1N,因此队伍中的第一头奶牛位于位置 1,第二头位于位置 2,依此类推,直到位置 NNN

一次洗牌由 NNN 个数字 a1…aNa_1 \ldots a_Na1aN 描述,其中位于位置 iii 的奶牛在洗牌期间移动到位置 aia_iai(因此,每个 aia_iai 都在 1…N1 \ldots N1N 范围内)。每头奶牛在洗牌期间都会移动到它的新位置。不幸的是,所有的 aia_iai 不一定互不相同,因此多只奶牛可能会在洗牌期间尝试移动到同一位置,之后它们将在所有剩余的洗牌中一起移动。

Farmer John 注意到,无论进行多少次洗牌,他的队伍中某些位置始终会有奶牛。请帮助他计算这样的位置数量。

输入格式

输入的第一行包含 NNN,表示奶牛的数量。第二行包含 NNN 个整数 a1…aNa_1 \ldots a_Na1aN

输出格式

请输出无论进行多少次洗牌,始终会有奶牛的位置数量。

输入输出样例 #1

输入 #1

4
3 2 1 3

输出 #1

3

在什么情况下,会有位置始终有奶牛?答案是有环。我们只需要统计环的数量即可。
利用拓扑排序,可以直观地计算环的数量。

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n;
    cin>>n;
    vector<int> target(n+1);
    vector<vector<int>> g(n+1);
    vector<int> in_(n+1, 0);
    for(int i = 1;i<=n;i++){
        cin>>target[i];
        g[i].push_back(target[i]);
        in_[target[i]]++;
    }
    vector<int> ans;
    priority_queue<int, vector<int>, greater<>> pq;
    for(int i = 1;i<=n;i++){
        if(!in_[i]) pq.emplace(i);
    }
    while(!pq.empty()){
        int v = pq.top();
        pq.pop();
        ans.push_back(v);
        if(!in_[v]){
            for(auto i : g[v]){
                in_[i]--;
                if(!in_[i]) pq.emplace(i);
            }
        }
    }
    cout<<n - ans.size();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值