做题记录整理并查集4 [NOIP2010 提高组] 关押罪犯(2022/9/16)
这题大部分题解使用的都是并查集+二分图染色,但是我刚刚惊人的发现这题才是真正的种类并查集模板题(而不是某个很难入手的食物链。。。)
首先开一个二倍的并查集,1n该囚犯的朋友,n+1n*2存该囚犯的敌人
我们首先进行排序,优先处理影响力较大的囚犯
对于一对囚犯,我们看看
如果gf(x)==gf(y) 表示这两个人现在已经是朋友了,你就不能再让他们变成敌人
如果gf(x+n)==gf(y+n),表示x的敌人是y的敌人,敌人的敌人就是朋友嘛,所以这两个人也算是朋友,不能拆开他们,若x再和y敌对,我们会发现y的敌人集合里有x,但x又和y的敌人相互敌对,这很明显是错误的
合并: fa[gf(x+n)]=gf(y); x的敌人集合加入y
fa[gf(x)]=gf(y+n); x的朋友集合加入y的敌人
#include<bits/stdc++.h>
#define for1(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
struct node{
	int x;
	int y;
	int w;
}a[500005];
int fa[500005];
int n,m,ans;
int gf(int x)
{
	if(fa[x]==x) 
		return x;
	return fa[x]=gf(fa[x]);
}
bool cmp( node x,node y)
{
	return x.w>y.w;
}
int main()
{
	cin>>n>>m;
	for1(i,1,n) fa[i]=i,fa[i+n]=i+n;
	for1(i,1,m)
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
	sort(a+1,a+m+1,cmp);
	for1(i,1,m)
	{
		int x=a[i].x;
		int y=a[i].y;
		if(gf(x)==gf(y)||gf(x+n)==gf(y+n))
		{
			cout<<a[i].w;
			return 0;
		}
		else{
			fa[gf(x+n)]=gf(y);
			fa[gf(x)]=gf(y+n);
		}
	}
	cout<<0<<endl;
	return 0;
 }

 
     
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号