抓捕盗窃犯(并查集)
生活随笔
收集整理的這篇文章主要介紹了
抓捕盗窃犯(并查集)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
題目描述
Q市發生了一起特大盜竊案。這起盜竊案是由多名盜竊犯聯合實施的,你要做的就是盡可能多的抓捕盜竊犯。
已知盜竊犯分布于?N?N個地點,以及第?i?i個地點初始有?ai?ai名盜竊犯。
特別的是,對于每一個地點?u?u,都有一個固定的地點?v?v--當前如果某個盜竊犯位于地點?u?u,在下一個時刻他會移動到地點?v?v。
你需要通過初始時在某些點設置哨卡來捉住他們。
現在你可以在?M?M個地點設置哨卡,如果在某個地點設置哨卡,你可以抓獲在任一時刻經過該地點的盜竊犯。
也就是說,哨卡存在的時間是無限長,但哨卡不能移動。
輸入描述:
第一行兩個整數?N,M(1≤N,M≤105)?N,M(1≤N,M≤105)。 第二行?N?N個整數?a1a2...aN?a1a2...aN?(0≤a1,a2,...aN≤105)?(0≤a1,a2,...aN≤105),表示第?i?i個地點初始有?ai?ai名盜竊犯。 第三行?N?N個整數?v1v2...vN?v1v2...vN?(1≤v1,v2,...vN≤N)?(1≤v1,v2,...vN≤N),表示當前處于地點?i?i的盜竊犯下一個時刻會移動到地點?vi?vi。輸出描述:
輸出一行一個整數--能夠抓捕到的最大數量。示例1
輸入
復制
8 2 1 2 3 4 1 2 3 12 2 3 3 3 6 7 5 8輸出
復制
22說明
對于樣例一,一種可行的方案是:在地點3、地點8分別設置一個哨卡,此時答案為1+2+3+4+12=22示例2
輸入
復制
8 2 1 2 3 4 5 6 7 8 2 3 4 5 6 7 8 8輸出
復制
36說明
對于樣例二,一種可行的方案是:在地點2、地點8分別設置一個哨卡,此時答案為1+2+3+4+5+6+7+8=36代碼:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream>typedef long long ll; using namespace std; int a[100005]; ll pre[100005]; ll b[100005]; ll find(ll x) {if(pre[x]==x){return x;} else{return pre[x]=find(pre[x]);} } void merge(int x,int y) {ll fx=find(x);ll fy=find(y);if(fx!=fy){pre[fx]=fy;} } int main() {int n,m;cin>>n>>m;for(int t=1;t<=n;t++){scanf("%d",&a[t]);}for(int t=1;t<=n;t++){pre[t]=t;}int x;for(int t=1;t<=n;t++){scanf("%d",&x);merge(x,t);}for(int t=1;t<=n;t++){b[find(t)]+=a[t];}sort(b+1,b+n+1);ll s=0;for(int t=n;t>=n-m+1;t--){s+=b[t];}cout<<s<<endl;return 0; }?
轉載于:https://www.cnblogs.com/Staceyacm/p/10781793.html
總結
以上是生活随笔為你收集整理的抓捕盗窃犯(并查集)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Asp.Net登陆记住用户功能实现
- 下一篇: pwnable.tw unexplo