codevs 1069 关押罪犯 并查集

很有意思的一道题。刚开始看不出这是道并查集,后来看了题解才会做,就是把要分开的囚犯放在同个集合里,表示这两个囚犯不在同一间监狱,但不是直接合并,例如1和2要分开,则1和2’、1’和2合并(x’为x的虚点),同个集合中实点和虚点分属于两间监狱(即x’与y在不同监狱);再例如,1和2,2和3要分开,则1和2’合并,2’和3合并,那么1和3会在同一间监狱,1’和2合并,2和3’合并,那么2就在另一间监狱。这样一来整道题的思路就呼之欲出了:按仇恨值从大到小分开每对囚犯,若出现无法分开的情况(即已在同一个监狱),则返回这对仇恨值并退出。附上AC代码:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define maxn 233333
 5 using namespace std;
 6 struct node{
 7     int a,b,c;
 8 };
 9 node e[maxn];
10 int N,M,fa[maxn];
11 int read();
12 bool cmp(node,node);
13 int getf(int);
14 int main(){
15     N=read();M=read();
16     for(int i=1;i<=N*2;i++)fa[i]=i;
17     for(int i=1;i<=M;i++)e[i].a=read(),e[i].b=read(),e[i].c=read();
18     sort(e+1,e+M+1,cmp);
19     for(int i=1;i<=M;i++){
20         int t1=getf(e[i].a),t2=getf(e[i].b);
21         if(t1==t2){
22             printf("%d",e[i].c);
23             return 0;
24         }
25         fa[t1]=getf(e[i].b+N);
26         fa[t2]=getf(e[i].a+N);
27     }
28     putchar(‘0‘);
29     return 0;
30 }
31 int read(){
32     int ans=0,f=1;char c=getchar();
33     while(‘0‘>c||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
34     while(‘0‘<=c&&c<=‘9‘)ans=ans*10+c-48,c=getchar();return ans*f;
35 }
36 bool cmp(node x,node y){
37     return x.c>y.c;
38 }
39 int getf(int x){
40     return fa[x]==x?x:getf(fa[x]);
41 }

并查集(补集的运用)

这道题中的并查集运用了补集的思想(在同一范围内,x的补集为w,y的补集为w,那么x和y会在同一个集合之中),有趣。

时间: 2024-10-06 12:27:14

codevs 1069 关押罪犯 并查集的相关文章

洛谷P1525 关押罪犯 并查集

无冲突 输出 0 洛谷P1525 关押罪犯 并查集 用拆点法 将一个点拆成两份 一个点和 x 的朋友相连 一个点和 x的敌人相连 若 x 与 y 是敌人 因为只有两个阵营 所以满足敌人的敌人就是朋友 然后 x 连向 y 的敌人 y 连向 x 的敌人 因为这是双向边 所以 y的朋友就是x的敌人就不用连了 如果某一时刻 getfather(e[ i ].from)==getfather(e[ i ].to) 这说明两个点已经是敌人关系的两个人 通过朋友关系连上了 那就结束了 1 #include <

codevs 1069关押罪犯

传送门 1069 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamon 题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨 气值"(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他

NOIP2010关押罪犯[并查集|二分答案+二分图]

题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c 的冲突事件. 每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里.公务繁忙的Z 市长只会去看列表

洛谷 P1525 关押罪犯==codevs 1069 关押罪犯[NOIP 2010]

P1525 关押罪犯 513通过 1.4K提交 题目提供者该用户不存在 标签图论并查集NOIp提高组2010 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 咳咳.竟MLE了. 囧.运行时错误,错误编号-… 点2是何方神圣? 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多.

codevs 1069 关押罪犯 2010年NOIP全国联赛提高组

时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨气值为c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并 造成影响力为c 的冲突事件. 每年年末,警察局

[noip2010]关押罪犯 并查集

第一次看的时候想到了并查集,但是不知道怎么实现: 标解,f[i]表示i所属的集合,用f[i+n]表示i所属集合的补集,实现的很巧妙,可以当成一个使用并查集的范例: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<map> 6 #include<ctime> 7 #include<vector>

洛谷P1525关押罪犯——并查集

题目:https://www.luogu.org/problemnew/show/P1525 并查集+贪心,从大到小排序,将二人分在不同房间,找到第一个不满足的即为答案. 代码如下: #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,m,fa[20005],ans,ct,d[20005]; struct N{ int hd,to,w; }edge[1000

P1525 关押罪犯 并查集

题目链接:https://www.luogu.org/problemnew/show/P1525 一道很难想到思路的题,还可以用二分图染色法,但我们只考虑并查集 要使得冲突最小,首先我们应该让冲突大的尽可能的不在同一个监狱 如果两个相互冲突的人都与第三个人冲突,那么应优先让冲突大的在不同的监狱 那么冲突小的冲突就是不可避免地冲突 如果整个过程都按照冲突的大小从大到小进行的话第一个不可避免的冲突就是将会发生的冲突中最大的一个 用并查集来实现的话,就是将敌人的敌人与自己放在同一个集合中,在同一个集合

1069 关押罪犯

codevs——1069 关押罪犯 洛谷——P1525 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极 不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨 气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之 间的积怨越多.如果两名怨