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