並查集 牛客練習賽41 C抓捕盜竊犯

題目連接 :https://ac.nowcoder.com/acm/contest/373/Cc++

題意,初始每個城市都有一夥盜賊,沒過一個時刻盜賊就會逃竄到另外一個城市,你能夠在m個城市設置監察站,會逮捕全部通過該城市的盜賊spa

分析:仔細分細題目,由於每一個城市的盜賊都是流動的,這就可能會造成環,而若是成環的話,在環所在任一城市均可以把這批城市的所有盜賊逮捕,就不須要再環上設多個監察站了,進一步推廣,由於能夠本身往本身的城市跑,因此也有多是鏈,而鏈也是知足設一個監察站能夠逮捕全部code

天然想到引入並查集,用map來保存blog

 1 #include <bits/stdc++.h>
 2 using  namespace std;  3 typedef long long ll;  4 const int maxn=1e5+7;  5 const int mod=1e9+7;  6 ll a[maxn],v[maxn];  7 ll par[maxn];  8 ll rnk[maxn];  9 ll c[maxn]; 10 bool cmp(const ll &a,const ll &b){ 11     return a>b; 12 } 13 void init(){ 14     for(ll i=0;i<maxn;i++) par[i]=i,rnk[i]=0; 15 } 16 ll find(ll x){ 17     if(par[x]==x){ 18         return x; 19  } 20     else{ 21         return par[x]=find(par[x]); 22  } 23 } 24 void unite(ll x,ll y){ 25     x=find(x);y=find(y); 26     if(x==y) return ; 27     if(rnk[x]<rnk[y]){ 28         par[x]=y; 29     }else { 30         par[y]=x; 31         if(rnk[x]==rnk[y]) rnk[x]++; 32  } 33 } 34 bool same(ll x,ll y){ 35     return find(x)==find(y); 36 } 37 int main(){ 38     ll n,m;scanf("%lld%lld",&n,&m); 39  init(); 40     for(int i=1;i<=n;i++){ 41         scanf("%lld",&a[i]); 42  } 43     for(int i=1;i<=n;i++){ 44         scanf("%lld",&v[i]); 45  unite(i,v[i]); 46  } 47     map<ll,ll> ans; 48     map<ll,ll>::iterator ite; 49     for(ll i=1;i<=n;i++){ 50         ans[find(i)]+=a[i]; 51  } 52     //for(int i=1;i<=n;i++) cout<<find(i)<<" ";
53     int j=0; 54     for(ite=ans.begin();ite!=ans.end();++ite){ 55         c[j++]=ite->second; 56  } 57     sort(c,c+ans.size(),cmp); 58     ll cnt=0; 59     for(ll i=0;i<m&&i<ans.size();i++){ 60     cnt+=c[i];}//cout<<c[i]<<endl;}
61     cout<<cnt<<endl; 62     return 0; 63 }
相關文章
相關標籤/搜索