关押罪犯(并查集维护二分图)

关押罪犯(并查集维护二分图)

传送门

题意:n个犯人与m对关系,每对关系的值表示仇恨值,将犯人分在两和监狱,如两个犯人间有关系且在相同的监狱就会共享仇恨值,求合理分配犯人后最低的仇恨值。

题解:此题考察的是用并查集构造二分图,先将关系的仇恨值由大到小排序,然后枚举关系,例如u,v,c分别表示两个犯人和仇恨值,如果u和v的祖宗不同,说明它们现在不在一个监狱,那么我们可以将u与v+n连边,u+n与v连边,(n+v表示非v,即u与v不在一个监狱,之后祖宗相同的情况是因为某点要与v不在一个监狱故与v+n连边,所以与u是同一个祖宗)

#include<iostream>
#include<algorithm>
using namespace std;
struct madoka{
	int u,v,c;
}ma[100007];
bool cmp(madoka a1,madoka a2){
	return a1.c>a2.c;
}
int n,m,u,v,c;
int fa[40007];
int fin(int p){
	if(fa[p]==p)return p;
	else{
		return fa[p]=fin(fa[p]);
	}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n*2;i++){
		fa[i]=i;
	}
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&ma[i].u,&ma[i].v,&ma[i].c);
	}
	sort(ma+1,ma+1+m,cmp);
	int ans=0;
	for(int i=1;i<=m;i++){
		if(fin(ma[i].u)!=fin(ma[i].v)){
			fa[fin(ma[i].u)]=fin(ma[i].v+n);
			fa[fin(ma[i].u+n)]=fin(ma[i].v);
		}
		else{
			ans=ma[i].c;
			break;
		}
	}
	printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/whitelily/p/13962054.html