题目链接:抓捕盗窃犯

仔细想一下图的构成就可以看出,一个点一个出度,所以对于每一个联通块比构成环,在环上随便一个点设置哨卡就能抓到联通块所有人。

所以我们找到m个最大的联通块即可。

更复杂的图可以用Tarjan,但是我们这道题直接并查集即可。


AC代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int f[N],n,m,a[N],b[N],res;
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
int cmp(int a,int b){return a>b;}
signed main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)   scanf("%lld",&a[i]),f[i]=i;
    for(int i=1,x;i<=n;i++){
        scanf("%lld",&x);   x=find(x); int y=find(i);    f[x]=y;
    }
    for(int i=1;i<=n;i++)   b[find(i)]+=a[i];
    sort(b+1,b+1+n,cmp);
    for(int i=1;i<=n&&m;i++,m--)    res+=b[i];
    cout<<res<<endl;
    return 0;
}