【NOIP2010】关押罪犯

一道感觉不错的并查集的题目

我们先将每一组矛盾关系按照冲突值从大到小排序,然后顺序扫描一遍,让冲突值大的两个人尽可能不在一个监狱里,如果不能满足,那么答案就是这组关系的矛盾值。如果所有的矛盾都不会发生,那么答案就是0.

之后我们建立并查集,另外定义一个辅助的数组d表示每一个人的一个敌人。我们扫描每一对关系,如果这两个人为了满足前面的条件已经在同一所监狱,那么答案就是他们的冲突值。否则,我们检查这两个人分别于对方的敌人合并即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 struct node {
 8     int a,b,c;
 9     bool operator <(const node &x) const {
10         return c<x.c;
11     }
12 }aa[100010];
13 int n,m;
14 int f[100010],d[100010];
15 int find(int x) {
16     if(f[x]!=x) return f[x]=find(f[x]);
17     return f[x];
18 }
19 void add(int x,int y) {
20     int fx=find(x);
21     int fy=find(y);
22     f[fy]=fx;
23 }
24 int main() {
25     scanf("%d%d",&n,&m);
26     for(int i=1;i<=n;i++) f[i]=i;
27     for(int i=1;i<=m;i++) {
28         scanf("%d%d%d",&aa[i].a,&aa[i].b,&aa[i].c);
29     }
30     sort(aa+1,aa+m+1);
31     reverse(aa+1,aa+m+1);
32     for(int i=1;i<=m;i++) {
33         if(find(aa[i].a)==find(aa[i].b)) {
34             printf("%d\n",aa[i].c);
35             return 0;
36         }
37         if(!d[aa[i].a]) d[aa[i].a]=aa[i].b;
38         else add(aa[i].b,d[aa[i].a]);
39         if(!d[aa[i].b]) d[aa[i].b]=aa[i].a;
40         else add(aa[i].a,d[aa[i].b]);
41     }
42     puts("0");
43     return 0;
44 }
AC Code

 

转载于:https://www.cnblogs.com/shl-blog/p/10922090.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值