♻️lzhh_lzhh32 • 3个月前
/*
1.假设树最小边是第i个边(已排序)
2.比它大的到m
3.使用kruscal最长边尽可能小
*/
//最小边最大,最大边最小
#include<iostream>
#include<algorithm>
using namespace std;
struct edge{
int a,b;
int len;
bool operator < (edge e2){ //重载运算符
return len<e2.len;
}
}list[2000005];
int n,m;
int group[100005]; //连通分量看作一组组 group[i]的值表示编号为i的节点属于那个连通分量
int find(int x){ //并查集 查连通分量编号
if(x!=group[x]){ //并不是自己的编号
group[x]=find(group[x]); //去查与自己连通的编号
}
return group[x]; //相等,返回自身组号
}
int main(){
cin>>n>>m; //n点m边
for(int i=0;i<m;i++){
cin>>list[i].a>>list[i].b>>list[i].len;
}
//输入
sort(list,list+m);
int ans=1000000000;
for(int i=0;i<m-1;i++){ //不断假设i是最小权值边来生成树
int start=i; //目前考虑的边的下标
for(int j=1;j<=n;j++) group[j]=j; //初始化并查集
for(int j=0;j<n-1;j++){ //选n-1条边出来生成树
while(start<m&&find(list[start].a)==find(list[start].b)){ //如果在同一个连通分量
start++; //这条边不能要,跳过
}
if(start==m) break; //如果以i为最小权值边已经不能生成树了,那么i和比i更大的更不能要
group[find(list[start].a)]=group[find(list[start].b)]; //合并连通分量编号
}
//以上为建树(36-44)
if(start==m) break; //如果以i为最小权值边已经不能生成树了,那么i和比i更大的更不能要,上次没切完,这次继续切出
ans=min(ans,list[start].len-list[i].len); //生成树完成后,start的下标就在最大生成树的最大权值边,减去i边的权值,即为所求差
}
cout<<ans<<endl;
return 0;
}
评论:
请先登录,才能进行评论