这一题的题目非常复杂,但是当你读懂了之后,就会发现其实是求各个生成树中最小的最大边。
如果你知道最小生成树的一个性质:最小生成树一定是瓶颈生成树,那这道题就迎刃而解了。
首先,要明白什么是瓶颈生成树。瓶颈生成树是一棵 “ 树上最大边权值 edge 在图G的所有生成树中最小 ” 的生成树,利用这个特点,我们只需要求出最小生成树,找到它的最大边,那这题就解决了。
本题我用的是kruskal算法求出最小生成树。
以下是完整代码:
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int root;
struct edge{
int start,end;
int w;
};
edge e[200000];
int pre[200000];
bool comp(edge e1,edge e2)
{
if(e1.w<e2.w)
return true;
else
return false;
}
int find(int x)//并查集的查找
{
if(pre[x]==x)
return x;
else
return pre[x]=find(pre[x]);
}
void unite(int x,int y)//并查集的合并
{
int a=find(x);
int b=find(y);
if(a!=b)
{
pre[a]=b;
}
}
void kruskal()
{
sort(e+1,e+m+1,comp);
int cnt=0;
int ans=0;
for(int i=1;i<=m;i++)
{
if(cnt==n-1)//当cnt=n的时候,说明所有的点都被连接起来了
{
break;
}
int a=find(e[i].start);//并查集操作
int b=find(e[i].end);
if(a!=b)//a!=b说明边e[i]的两个端点不在同一个集合里,说明选择边e[i]不会形成环
{
cnt++;
ans=max(ans,e[i].w);
unite(e[i].start,e[i].end);//说明边的两个端点已经属于同一集合了
}
}
cout<<ans<<'\n';
}
int main()
{
cin>>n>>m>>root;
for(int i=1;i<=m;i++)
{
pre[i]=i;
}
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
e[i].start=u;
e[i].end=v;
e[i].w=w;
}
kruskal();
}