洛谷 P1525 拓展域并查集

https://www.luogu.com.cn/problem/P1525#submit

题意

现在要将n个囚犯关进两个监狱,其中有m个敌对关系,将两个敌人关在一个监狱会产生一个代价w,请你最小化代价w的最大值

这个代价一定出自w,所以我们尽量不要取到较大的w,所以我们按w从大到小排序,将两个人分配到两个监狱。
考虑并查集,设\(fa[i+n]\)为我敌人所在的监狱,我们对两个囚犯\(u,v\)自然是要把\(u\)分到\(v\)的敌人所在的监狱,\(v\) 分配到\(u\)的敌人所在的监狱,也就是把\(fa[u+n]\)\(fa[v]\),\(fa[v+n]\)\(fa[u]\) 合并
如果查到\(u, v\)在一个集合里那么我们直接输出这个w,如果所有的关系都找完没有输出w,那么输出0;

代码

点击查看代码
#include <bits/stdc++.h>

using namespace std;

const int MAXN = 400010;

int fa[MAXN], n, m;

struct book
{
	int u, v, w;
}ar[MAXN];

bool cmp(struct book &a, struct book &b)
{
	return a.w > b.w;
}
/*------------------并查集合并------------------*/
int find(int x)
{
	if(fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);
	cin >> n >> m;
	for(int i = 0; i < m; i++)
	{
		cin >> ar[i].u >> ar[i].v >> ar[i].w;
	}
	for(int i = 1; i <= 2 * n; i++)
	{
		fa[i] = i;
	}
	sort(ar, ar + m, cmp);
	for(int i = 0; i < m; i++)
	{
		if(find(ar[i].u) == find(ar[i].v))  //如果u, v在一个监狱输出 w 
		{
			printf("%d", ar[i].w);
			return 0;
		}
		else 
		{
			fa[find(ar[i].u + n)] = find(ar[i].v); // 合并 u + n, v 
			fa[find(ar[i].v + n)] = find(ar[i].u); // 合并 v + n, u 
		}
	}
	printf("0");
	return 0;
}
posted @ 2025-08-01 17:37  东东哥本人  阅读(7)  评论(0)    收藏  举报