题解:
(1)我们需要先对所有边的权值(也就是矛盾值)按照权值从大到小的顺序进行排序,为什么要排序呢,因为我们需要尽量把两个仇恨值大的罪犯分到不同的集合,所以要先对他们进行处理。
(2)然后这里有一个原则,就是敌人的敌人可能是朋友,怎样理解这句话呢?可以理解为自己的两个敌人可能是朋友,我们把自己的两个敌人分到一个集合中,自己在一个集合,他们之间可能不存在矛盾,此时就是最优化的选择
(3)当我们处理一条边的两个顶点时,若此时它们已经在一个集合中,说明矛盾是不可避免的,这时就可以停止,直接输出这条边的权值即可。
(4)最后注意输出0的情况。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<map>
#define MAX 20005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,m,fa[MAX],enemy[MAX];
struct edge{
int w;//边的权值
int s;//边的起点
int f;//边的终点
edge(int ss,int ff,int ww){
s=ss;
f=ff;
w=ww;
}
bool operator < (const edge &a) const{//最大值优先
return w>a.w;
}
};
int findfather(int x){
if(x!=fa[x]){
return findfather(fa[x]);
}else{
return fa[x];
}
}
void _union(int a,int b){
int aa=findfather(a);
int bb=findfather(b);
if(aa!=bb){
fa[aa]=bb;
}
}
vector<edge> e;
int main(){
scanf("%d%d",&n,&m);
int a,b,c;
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
edge tmp(a,b,c);
e.push_back(tmp);
}
sort(e.begin(),e.end());
for(int i=0;i<MAX;i++){//初始化
fa[i]=i;
}
for(int i=0;i<m;i++){
int t1=findfather(e[i].s),t2=findfather(e[i].f);
if(t1==t2){//如果s和f已经在同一集合,则直接结束
printf("%d",e[i].w);
return 0;
}
int s=e[i].s,f=e[i].f;
//自己的两个敌人可能是朋友,其实也就是敌人的敌人就是朋友
if(!enemy[s]) enemy[s]=f;
else _union(enemy[s],f);
if(!enemy[f]) enemy[f]=s;
else _union(enemy[f],s);
}
printf("0");//说明不存在矛盾
return 0;
}