1. 程式人生 > >P1525-關押罪犯【並查集】

P1525-關押罪犯【並查集】

正題

題目大意

有n個罪犯,罪犯有些關係,就是(i,j,c)表示罪犯i和罪犯j在同一個監獄會造成c的破壞,有兩座監獄,要求分配的使得最大的破壞最小。

解題思路

先按照c排序,然後就從大到小處理直到無法處理。 我們可以用並查集表示在一個監獄中,然後用敵人的敵人是朋友來合併。記錄每個罪犯的敵人的根,然後每次合併就將他的敵人和他的敵人合併在一起,直到發現一個人即是某人的敵人有是某人敵人的敵人就輸出。

code

#include<cstdio>
#include<algorithm>
#define N 20010
using
namespace std; struct node{ int x,y,c; }a[N*5]; int n,m,father[N],empty[N]; bool cmp(node x,node y) {return x.c>y.c;} int find(int x)//尋找 { if(father[x]==x) return x; return father[x]=find(father[x]); } void unionn(int x,int y)//合併 { int fa=find(x),fb=find(y); father[fa]=fb; } int
main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c); for(int i=1;i<=n;i++) father[i]=i; sort(a+1,a+1+m,cmp); for(int i=1;i<=m;i++) { if(find(a[i].x)==find(a[i].y))//出現問題 { printf
("%d",a[i].c); return 0; } else { if(!empty[a[i].x]) empty[a[i].x]=a[i].y; else unionn(empty[a[i].x],a[i].y); if(!empty[a[i].y]) empty[a[i].y]=a[i].x; else unionn(empty[a[i].y],a[i].x); //連線——敵人的敵人 } } printf("0"); }