题意
有N个节点M条边的图,将N个节点分成两个集合,使每个集合内部连边的边权值和的最大值最小。
分析
边权最大的两个优先不在一起。因此,我们必须对边权由大到小排序。又因为与自己的敌人不在一个集合,那么敌人的敌人跟自己就在一个集合,合并一下即可。以此类推,直到两个人不得不在一个集合,那么他们两个之间的边权就是答案(因为拍过序,所以直接就是最大值)
另外,一个细节,循环中若到了m+1,就会输出0,因为都不连通。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
int x,y,z;
}a[100010];
int n,m,v[20010],fa[20010];
int cmp(node l,node r)
{
return l.z>r.z;
}
int find(int x)
{
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
inline void hb(int x,int y)
{
x=find(fa[x]);
y=find(fa[y]);
fa[x]=y;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m+1;i++)
{
if(find(a[i].x)==find(a[i].y))
{
cout<<a[i].z;
break;
}
else
{
if(!v[a[i].x]) v[a[i].x]=a[i].y;
else hb(v[a[i].x],a[i].y);
if(!v[a[i].y]) v[a[i].y]=a[i].x;
else hb(v[a[i].y],a[i].x);
}
}
return 0;
}