noip 2010 关押罪犯 二分答案+二分图染色 || 并查集
题目链接
题目描述
S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件。
每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。
在详细考察了N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。
那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?
思路
法一:二分答案+二分图染色
如果这是一个二分图,那么就能达到完全不发生冲突事件的效果。
所以,我们可以考虑在原图上删去若干条边得到一个二分图。在这个二分图中,是没有冲突事件发生的。然后再加上刚刚删去的边,必然是在染成同一个颜色的点之间加边,因此所加的这些边就代表着会发生的冲突事件。
因此,就要使得删去的边的权值最小。而在之后所有加进去的边中只有权值最大的那条边有意义,因为是它决定了所有冲突事件中最大的影响力,权值比它小的边加进去也无关紧要。
因为具有单调性,可以先排序再二分答案删去的最大的一条边,将小于它的边全部删去然后\(check\).
法二:并查集
思路很巧妙。也是因为这个我才想明白了用并查集判断二分图是什么原理。
这道题最根本的想法其实就是要将怒气值最大的一对对犯人分开,而并查集是用来处理等价关系的,并且不等关系不具有传递性,怎么办呢?
那就将不等关系转化为等价关系。
将\(i+n\)看作\(i(1\leq i\leq n)\)的敌人。那么在分开\(u,v\)时,说明\(u\)是\(v\)的敌人,因此\(u\)和\(v+n\)是一类,\(v\)和\(u+n\)是一类,于是可以将它们分别合并。如果哪次发现要分开的两个点已经在同一个集合中,就说明这两个点已经分不开了。因为是从大往小合并,当前这条边的权值就是会发生的冲突的最大值。
比较
从具体实现可见,法一要做\(logn\)次并查集,而法二只要做一次并查集。
因为出发点是不同的,法一是从二分图染色出发,而法二本身就是并查集的思路。可见二分图和并查集关系紧密,以后要多想想是否能够进行转化。
Code
Ver. 1
#include <bits/stdc++.h>
#define maxn 40010
#define maxm 100010
using namespace std;
typedef long long LL;
int fa[maxn], sz[maxn];
struct node {
int u, v, val;
bool operator < (const node& nd) const {
return val < nd.val;
}
}a[maxm];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
void unionn(int x, int y) {
x = find(x), y = find(y);
if (x == y) return;
if (sz[x] > sz[y]) swap(x, y);
fa[x] = y, sz[y] += sz[x];
}
int n, m;
bool check(int id) {
for (int i = 1; i <= (n<<1); ++i) sz[i] = 1, fa[i] = i;
for (int i = id+1; i < m; ++i) {
if (find(a[i].u) == find(a[i].v)) return false;
unionn(a[i].u, a[i].v+n);
unionn(a[i].v, a[i].u+n);
}
return true;
}
int main() {
freopen("prison.in", "r", stdin);
freopen("prison.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 0; i < m; ++i) scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].val);
sort(a, a+m);
int l = -1, r = m-1;
while (r > l) {
int mid = l+r>>1;
if (check(mid)) r = mid;
else l = mid+1;
}
if (~l) printf("%d\n", a[l].val);
else printf("0\n");
return 0;
}
Ver.2
#include <bits/stdc++.h>
#define maxn 40010
#define maxm 100010
using namespace std;
typedef long long LL;
int fa[maxn], sz[maxn];
struct node {
int u, v, val;
bool operator < (const node& nd) const {
return val > nd.val;
}
}a[maxm];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
void unionn(int x, int y) {
x = find(x), y = find(y);
if (x == y) return;
if (sz[x] > sz[y]) swap(x, y);
fa[x] = y, sz[y] += sz[x];
}
int n, m;
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < m; ++i) scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].val);
sort(a, a+m);
for (int i = 1; i <= (n<<1); ++i) sz[i] = 1, fa[i] = i;
for (int i = 0; i < m; ++i) {
if (find(a[i].u) == find(a[i].v)) { printf("%d\n", a[i].val); exit(0); }
unionn(a[i].u, a[i].v+n);
unionn(a[i].v, a[i].u+n);
}
printf("0\n");
return 0;
}
noip 2010 关押罪犯 二分答案+二分图染色 || 并查集的更多相关文章
- NOIP 2010 关押罪犯 并查集 二分+二分图染色
题目描述: S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值" ...
- noip 2010 关押罪犯 (二分图染色 并茶几)
/* 二分图染色版本 两个监狱对应二部图的两部分 在给定的怨气值里二分 对于每一个Ci 进行染色判断是否合法 染色的时候 如果这条边的ci > Ci 这两个人就带分开 即染成不同的颜色 如果染色 ...
- [NOIP 2010] 关押罪犯 (二分+二分图判定 || 并查集)
题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...
- NOIP 2010 关押罪犯
P1525 关押罪犯 题目描述 SS 城现有两座监狱,一共关押着 NN 名罪犯,编号分别为 1-N1−N .他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突. ...
- noip提高组 2010 关押罪犯 (洛谷1525)
题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...
- BZOJ 3993: [SDOI2015]星际战争 [二分答案 二分图]
3993: [SDOI2015]星际战争 题意:略 R1D2T1考了裸二分答案+二分图最大匹配... #include <iostream> #include <cstdio> ...
- HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流
二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...
- HDU 3081 Marriage Match II (二分图,并查集)
HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...
- NOIP提高组2010 关押罪犯
题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...
随机推荐
- dht 分布式hash 一致性hash区别
先有一致性hash :一致性哈希,似乎最早提出是在分布式缓存里面的,让节点震荡的时候,影响最小.不过现在已经应用在分布式存储和p2p系统里面. dht 是p2p领域的概念,内有三大概念是由keyspa ...
- C#基于联通短信Sgip协议构建短信网关程序
此软件基于中国联通Sgip协议程序接口,适合在中国联通申请了短信发送端口的公司使用.短信群发已经成为现在软件系统.网络营销等必不可少的应用工具.可应用在短信验证.信息群发.游戏虚拟商品购买.事件提醒. ...
- linux更新git
在CentOS中使用yum install git安装的git是1.7版本的,所以需要更新1.9以及更高版本的git. 安装方法如下: 1.安装依赖的包: yum -y install curl-de ...
- EXC_BAD_ACCESS调试
有时候,你会遇到由EXCBADACCESS造成崩溃. 这篇文件会告诉你什么是EXCBADACCESS,以及它产生的原因.我还会提供一些EXCBADACCESS错误的解决方案. 1. 什么是 EXCBA ...
- 函数的扩展——箭头函数this的使用
箭头函数中的this指向的是定义时的this,而不是执行时的的this . 举例: 案例中,我们的obj对象中有一个属性x和一个属性show( )方法,show( )通过this打印出x的值,结果是u ...
- stm32之ADC应用实例(单通道、多通道、基于DMA)
文本仅做记录.. 硬件:STM32F103VCT6 开发工具:Keil uVision4 下载调试工具:ARM仿真器 网上资料很多,这里做一个详细的整合.(也不是很详细,但很通俗). 所用的芯片内嵌 ...
- The Best Path HDU - 5883 欧拉通路
图(无向图或有向图)中恰好通过所有边一次且经过所有顶点的的通路成为欧拉通路,图中恰好通过所有边一次且经过所有顶点的回路称为欧拉回路,具有欧拉回路的图称为欧拉图,具有欧拉通路而无欧拉回路的图称为半欧拉图 ...
- jdk生成证书,网站请求变成https
生成证书的步骤 1.进入jdk的bin目录 keytool -genkey -alias tomcat -keyalg RSA 命名证书的名字叫tomcat 2.将证书拷贝至tomcat的bin目 ...
- Python 基础(一)
本章内容 1.编译和解释型语言的区别 2.Python的解释器 3.pyc文件 4.运行环境 5.变量 6.数据类型 7.字符编码 8.三元运算 编译和解释型语言的区别 编译器是把源程序的每一条语句都 ...
- 【NOIP2016】愤怒的小鸟 搜索
题目描述 Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0,0)(0,0) 处,每次 Kiana 可以用它向第一象限发射一只红色的小鸟,小 ...