洛谷 P1525 关押罪犯 解题思路: AC代码:

题目传送门

本题为加权并查集,首先看题,很容易想到的一个贪心策略就是尽可能把较大的分开。我们边权从大到小排序,尽可能把危害大的两个罪犯分开,再将敌人的敌人和自己合并。直到发现有一对有冲突的罪犯不可避免的被分到了一起,就输出冲突值,即为答案。如果一直到最后都没有冲突,输出0.

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 
 7 struct kkk {
 8     int a,b,c;
 9 }e[100001];
10 int n,m,fa[20001],vis[20001];
11 
12 bool cmp(kkk a1,kkk b1) {
13     return a1.c > b1.c;
14 }
15 
16 int find(int x) {
17     if(fa[x] == x) return x;
18     return fa[x] = find(fa[x]);
19 }
20 
21 bool check(int x,int y) {
22     int x1 = find(x);
23     int y1 = find(y);
24     if(x1 == y1) return true;
25     return false;
26 }
27 
28 void merge(int x,int y) {
29     x = find(fa[x]);
30     y = find(fa[y]);
31     fa[x] = y;
32 }
33 
34 int main() {
35     scanf("%d%d",&n,&m);
36     for(int i = 1;i <= n; i++)
37         fa[i] = i;
38     for(int i = 1;i <= m; i++) 
39         scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
40     sort(e+1,e+1+m,cmp);
41     for(int i = 1;i <= m; i++) {
42         if(check(e[i].a,e[i].b)) {//不可避免的分到了一起 
43             printf("%d",e[i].c);
44             return 0;
45         }
46         if(!vis[e[i].a]) vis[e[i].a] = e[i].b;//标记敌人 
47         else merge(vis[e[i].a],e[i].b);//将敌人的敌人与自己合并 
48         if(!vis[e[i].b]) vis[e[i].b] = e[i].a;
49         else merge(vis[e[i].b],e[i].a);
50     }
51     cout << 0;
52     return 0;
53 }

//NOIP提高 2010 T3