AC

♻️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;
}

评论:

请先登录,才能进行评论