#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
struct node {
int u,v,value;
}a[400000];
int cmp(struct node aa,struct node bb){
return aa.value>bb.value;
}
int n,m,fa[50000],k=0;
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].value);
sort(a+1,a+m+1,cmp);
for(int i=1;i<=n*2;i++) fa[i]=i;//避免死循环
for(int i=1;i<=m;i++){
int p=find(a[i].v);
int q=find(a[i].u);
if(p==q){
printf("%d",a[i].value);
k=1;
break;
}
else{
fa[p]=find(a[i].u+n);//在下一个集合中互相立为敌人
fa[q]=find(a[i].v+n);//在下一个集合中互相立为敌人
}
}
if(k==0) printf("0");
return 0;
}
引用题解:
总共只有两个集合,想一下这样的逻辑关系,a不和b在一起,a不和c在一起,那么b和c一定在一起。
将 i 的所有敌人放到fa[i]所指向的并查集中,在这里需要考虑一个问题,如果1和2互为敌人,而将fa[1]指向2、fa[2]指向1,那么会导致在并查集查找中出死循环。那么可以使用一种处理方法,将fa[i]指向fa[n+i]。
初始化时将所有的道路从大到小排序,优先处理影响力大的冲突。如果这个冲突不可以被解决,那么这个影响力一定是无法被解决的最大值。a[i]为正在处理的冲突,a[i].v和a[i].u为要发生的冲突的两人,而fa[a[i].v]和fa[a[i].u]分别为v和u的敌人,按照原有的想法,两人的敌人应该都不相同,这样两人才能被关入不同的监狱,但如果a和b有相同的敌人,显然并不能解决冲突。
在初始化时还存在一个问题,并不可以在初始的时候就将fa[i]指向fa[n+i]。因为当f[i]并没有和f[n+i]相连时,i节点相对独立,到i节点第一次出现时,这个冲突一定可以被解决,即i一定可以被关进某个监狱,但如果f[i]已经指向f[n+i],那么便有这个冲突无法被解决的可能。
引用题解 传送门 (点我)