题意:
样例输入:
4
5
1
1 2 3
1 3 4
1 4 5
2 3 8
3 4 2
样例输出:
4
样例说明:
思路:
题目分析:
已知无向图的边权,求生成树使最大边权最小
具体实现:
还是求生成树的问题,又因为求最大边权最小,所以要尽可能的使所选的边小,与kruskal算法吻合(每次尝试将最小的非树边标记为树边),所以我还是采用了kruskal,只是多记录一下最大边的权值
总结:
本题的关键是能从冗长的题目中提取有效信息,并明确题目的要求
代码:
#include<cstdio>
#include<list>
#include<algorithm>
using namespace std;
struct edge{
int from;
int to;
int weight;
edge(int a,int b,int c){from=a;to=b;weight=c;}
bool operator<(edge &e){
if(weight!=e.weight) return weight<e.weight;
}
};
int n,m,root,theMax;
list<edge> G;
int par[50001],ran[50001];
void init(int n){
for(int i=0;i<=n;i++){
par[i]=i; ran[i]=1;
}
}
int find(int x){
return par[x]==x?x:par[x]=find(par[x]);
}
bool unite(int x,int y){
x=find(x); y=find(y);
if(x==y) return false;
if(ran[x]>ran[y]) swap(x,y); //始终保证y为大树
par[x]=y; ran[y]=(ran[x]+=ran[y]); //这里注意两个rank都更新
}
void kruskal(){
init(n);
int num=0; //记录生成树中边的条数
while(num<n&&G.size()!=0){
int a=find(G.front().from);
int b=find(G.front().to);
if(a==b) G.pop_front(); //都在生成树中
else{
if(G.front().weight>theMax) theMax=G.front().weight;
unite(G.front().from,G.front().to); //合并
G.pop_front(); num++;
}
}
}
int main(){
int x,y,wi;
scanf("%d%d%d",&n,&m,&root);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&wi);
G.push_back({x,y,wi});
}
G.sort();
kruskal();
printf("%d\n",theMax);
return 0;
}