洛谷 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;
}
浙公网安备 33010602011771号