题目链接:抓捕盗窃犯
仔细想一下图的构成就可以看出,一个点一个出度,所以对于每一个联通块比构成环,在环上随便一个点设置哨卡就能抓到联通块所有人。
所以我们找到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;
}