P1525 关押罪犯 并查集

时间:2021-02-23 14:37:21

题目链接:https://www.luogu.org/problemnew/show/P1525

一道很难想到思路的题,还可以用二分图染色法,但我们只考虑并查集

要使得冲突最小,首先我们应该让冲突大的尽可能的不在同一个*

如果两个相互冲突的人都与第三个人冲突,那么应优先让冲突大的在不同的*

那么冲突小的冲突就是不可避免地冲突

如果整个过程都按照冲突的大小从大到小进行的话第一个不可避免的冲突就是将会发生的冲突中最大的一个

用并查集来实现的话,就是将敌人的敌人与自己放在同一个集合中,在同一个集合中的人发生的冲突就是无法避免的冲突

找到其中的最大值

整个过程要按冲突的大小顺序进行

 1 #include <bits/stdc++.h>
 2 using namespace std;  3 struct edge{  4     int from,to,cost;  5 };  6 edge G[100005];  7 int f[20005];  8 int e[20005];    //存储敌人
 9 
10 bool cmp(edge a,edge b){ 11     return a.cost>b.cost; 12 } 13 
14 int fa(int a){ 15     return f[a] == a?a:f[a] = fa(f[a]); 16 } 17 
18 bool check(int a,int b){ 19     return fa(a) == fa(b); 20 } 21 
22 void link(int a,int b){ 23     if(!check(a,b)) 24         f[fa(a)] = fa(b); 25 } 26 
27 int main() 28 { 29     int n,m; 30     cin>>n>>m; 31     for(int i=1;i<=n;++i) 32         f[i] = i; 33     for(int i=0;i<m;++i){ 34         int a,b,c; 35         cin>>a>>b>>c; 36         G[i].from = a; 37         G[i].to = b; 38         G[i].cost = c; 39  } 40     sort(G,G+m,cmp); 41     for(int i=0;i<=m;++i){    //如果没有发生冲突i=m
42         edge ans = G[i]; 43         if(check(ans.from,ans.to)){    //无法避免
44             cout<<ans.cost; 45             break; 46  } 47         else{ 48             if(!e[ans.from]) 49                 e[ans.from] = ans.to; 50             else
51                 link(ans.to,e[ans.from]); 52             if(!e[ans.to]) 53                 e[ans.to] = ans.from; 54             else
55                 link(ans.from,e[ans.to]); 56  } 57  } 58     return 0; 59  }