关押罪犯 - 并查集&优先队列

题目地址:http://www.51cpc.com/web/problem.php?id=4261

 

Summarize:

 此题最巧妙的是“敌人的敌人就是朋友!”,故需先将敌对关系放入优先队列,按怨恨值从大到小排序,建一个数组存储对应敌对关系,

 当遇到第二个以及后来的敌人时,将之前的敌人与后来的敌人放进一个监狱,直到遇见一对关系中两人已经关在统一监狱,即为最大值。

 

附代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<queue>
 8 #include<cmath>
 9 using namespace std;
10 
11 #define LL long long
12 const int N = 2e4+5;
13 int n,m, f[N], enemy[N];
14 struct RELA {
15     LL a, b, value;
16     friend bool operator<(const struct RELA &x, const struct RELA &y) {
17         return x.value<y.value;
18     }
19 };
20 
21 int find(int x) {
22     if(x != f[x])
23         f[x] = find(f[x]);
24     return f[x];
25 }
26 
27 bool Union(int a, int b) {
28     int x = find(a);
29     int y = find(b);
30     if(x == y) return false;
31     if(x != y) f[x]=y;
32     return true;
33 }
34 
35 int main()
36 {
37     ios::sync_with_stdio(false);
38     
39     while(cin>>n>>m)
40     {
41         LL a,b,value;
42         priority_queue<RELA> rela;
43         for(int i=1; i<=n; i++)
44             f[i]=i, enemy[i]=0;
45         for(int i=0; i<m; i++) {
46             cin>>a>>b>>value;
47             rela.push(RELA{a,b,value});
48         }
49         
50         bool can=true;
51         while(!rela.empty()) {
52             RELA t = rela.top();
53             rela.pop();
54             a=t.a, b=t.b, value=t.value;
55             
56             if(!enemy[a]) enemy[a]=b;
57             else Union(enemy[a],b);
58             if(!enemy[b]) enemy[b]=a;
59             else Union(enemy[b],a);
60             
61             if(find(a) == find(b)) {
62                 can=false;
63                 cout<<value<<endl;
64                 break;
65             }
66         }
67         if(can) cout<<0<<endl;
68     }
69 }

 

posted @ 2018-07-31 20:56  liubilan  阅读(135)  评论(0编辑  收藏  举报