codevs 1069 关押罪犯 (并查集)
来源:互联网 发布:医学搜题软件 编辑:程序博客网 时间:2024/04/27 17:16
题意:有n名罪犯,m个关系,每个关系(u, v, w)表示犯人u和v如果关在同一个监狱之间会产生怨气值w,现在有两个监狱,问你怎么放置着n个犯人,犯人之间最大怨气值最小,求这个值。N≤ 20000,M≤ 100000
思路:(点击打开链接)维护罪犯在哪一个监狱不方便,我们可以维护某两个罪犯是不是在一个监狱。考虑到并查集的本职工作是维护某两点在一个集合,不能很好地处理不在一个集合的情况,通过保存某个点的“敌人”集合来代表和他不在一个监狱的罪犯,间接地实现维护某两点不在一个集合的情况。在加入关系的时候进行判断,如果某两点已经在一个集合,说明他们无论如何也安排不到不同的两个监狱了,输出仇恨值即可;如果不在一个集合,就将犯人和对方的敌人合并到一个集合。
(敌人的敌人就是朋友)
代码:
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 1e5+5;struct node{ int u, v, w; bool operator <(const node &a) const { return w > a.w; }}a[maxn];int pre[maxn], en[maxn], n, m;int Find(int x){ int r = x; while(pre[r] != r) r = pre[r]; int i = x, j; while(i != r) { j = pre[i]; pre[i] = r; i = j; } return r;}void join(int x, int y){ int a = Find(x); int b = Find(y); if(a != b) pre[b] = a;}int main(void){ while(cin >> n >> m) { for(int i = 1; i <= n; i++) pre[i] = i, en[i] = 0; for(int i = 1; i <= m; i++) scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w); sort(a+1, a+1+m); int ans = 0; for(int i = 1; i <= m; i++) { int x = a[i].u; int y = a[i].v; int fa = Find(x); int fb = Find(y); if(fa == fb) { ans = a[i].w; break; } if(en[x]) join(y, en[x]); else en[x] = y; if(en[y]) join(x, en[y]); else en[y] = x; } printf("%d\n", ans); } return 0;}
用并查集表示每个犯人之间的关系,在同一个集合中则说明两人在同一个监狱,反之则不在同一个监狱。
用类似于克鲁斯卡尔的方法,先将边排序,然后按照仇恨值的大小从大到小处理。对于每一组,先看两个人能不能加入不同的集合,
如果可以,将两人加入不同的集合,如果不可以,则输出该组仇恨值。
用补集来表示两个点不在一个集合中。如a和b'在同一个集合中,则a和b不在同一个集合中,不能把b直接加入另一个集合,因为会对后面的结果产生影响。
如,3和4不在同一个集合中,但是我们现在不知道究竟是3在第一个监狱还是4在第一个监狱,所以此时用3和4‘在同一个集合中来表示3和4不在同一个集合中。
阅读全文
1 0
- codevs 1069关押罪犯 并查集
- codevs 1069 关押罪犯 并查集
- codevs 1069 关押罪犯 (并查集)
- Codevs 1069 && 洛谷 1525 关押罪犯 并查集
- 并查集1069 关押罪犯
- 关押罪犯 【并查集】
- 并查集 关押罪犯
- NOIP2010 Codevs 1069 关押罪犯 [并查集] [二分图判定]
- 【noip2010】codevs 1069 关押罪犯(二分+BFS染色||并查集)
- 关押罪犯 codevs 1069(整理:加权并查集?+虚点并查集+二分图染色)
- CODEVS 1069 关押罪犯
- Codevs-1069 关押罪犯
- 【codevs】1069 关押罪犯
- 【codevs 1069】关押罪犯
- CODEVS 1069关押罪犯
- codevs 1069 关押罪犯
- CODEVS 1069 关押罪犯
- 【codevs 1069】关押罪犯
- caffe在编译时注意事项
- 为什么L1正则项会产生稀疏解
- Spring AOP中pointcut expression表达式解析
- Go实战--golang中获取公网ip、查看内网ip、检测ip类型、校验ip区间、ip地址string和int转换、根据ip判断地区国家运营商等
- 【莫比乌斯反演】GCD1
- codevs 1069 关押罪犯 (并查集)
- 对相同原理图修改orcad前缀编号并在allegro拼异形板
- Python学习(一)
- 伪类选择器的用途
- 阿里云关闭防火墙端口不能外网访问
- 如何计算完全二叉树的深度
- [BZOJ1827][Usaco2010 Mar]gather 奶牛大集会(树形dp+维护)
- 视图上的委托
- Java| Java对象克隆Clone(1)