poj 3723 Conscription (并查集)
生活随笔
收集整理的這篇文章主要介紹了
poj 3723 Conscription (并查集)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1 首先我們應該區分開男孩和女孩,只要將男孩的編號加上女孩的個數n,這樣就可以做到男孩和女孩的編號是不同的。
2 題目中說了如果兩個人有關系,并且其中一個人已經被選了那么選擇另外一個人的時候只要10000-d即可。所以這就涉及到了兩個人的關系問題,那么自然的想到了并查集來保存關系圖。所以這n+m個人最后就可以被分到s個集合里面,每一個集合里面的人都是有關系的。那么這樣我們只要求出s個集合的最小生成樹相加,然后在加上s*10000(沒有關系的時候選擇一個人要10000),即為最后的答案。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define max 50005 using namespace std; int pre[20010],n,m,r,ans; struct edge {int u,v,w; }e[max]; int find(int x) {int r=x;while(pre[r]!=r)r=pre[r];int i,j=x;while(j!=r){i=pre[j];pre[j]=r;j=i;}return r; } bool cmp(struct edge a,struct edge b) {return a.w<b.w; } int dkstl() {for(int i=0;i<m+n;++i)pre[i]=i;int x,y;sort(e,e+r,cmp);for(int i=0;i<r;++i){x=find(e[i].u);y=find(e[i].v);if(x!=y){ans+=e[i].w;pre[x]=y;}}/* sort(pre,pre+2*n);//waint ant=1;for(int i=1;i<2*n;++i){if(pre[i]!=pre[i-1])ant++;}*/int d[20010],ant=0;memset(d,0,sizeof(d));for(int i=0;i<n+m;++i){x=find(i);if(!d[x]){ant++;d[x]=1;}}cout<<10000*ant+ans<<endl;return 0; } int main() {int t;cin>>t;while(t--){int u,v,w;cin>>n>>m>>r;for(int i=0;i<r;++i){scanf("%d %d %d",&u,&v,&w);e[i].u=u;e[i].v=v+n;e[i].w=10000-w;}ans=0;dkstl();}return 0; }
總結
以上是生活随笔為你收集整理的poj 3723 Conscription (并查集)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: poj 3255 Roadblocks
- 下一篇: 第四周实践项目2 算法库——单链表