UVA1395-Slim Span(最小生成树Kruskal、并查集)

题目链接:点击打开链接

题意:给你一个图,求一个生成树,使其苗条度最小

苗条度:生成树的最大边减去最小边的值。


先把边的权值从大到小排序,然后,对于任意一个边值区间,都可以建立生成树,使苗条度不超过这个图的最大边减最小边。

所以说,要想找出来这个苗条度最小的生成树,就要先枚举这个区间的左端点,在此基础去枚举右端点,比如说有三个权值是3,4,5的边,首先是[3],[3,4][3,4,5]分别去建树,然后比较苗条度,取最小的,这样,所有的方案都建成之后,最小的苗条度也就出来了,当然,边要足够连接所有的点,建不了树是没有结果的,返回-1

代码及注释如下:

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,cnt;
int a[11000],b[11000],w[11000],p[11000],r[11000];//a,b为点的序号。w为权值,p为并查集,r是边的序号 

int cmp(const int i,const int j)
{
	return w[i]<w[j];							//间接排序 
}

int find(int x)
{
	return p[x]==x?x:p[x]=find(p[x]);			//找根函数 
}

int solve()
{
	int ans=0x3f3f3f3f,t;
	for(int i=0;i<m;i++)r[i]=i;					//边序号初始化 
	sort(r,r+m,cmp);							//将边的权值从小到大排序 
	for(int i=0;i<m;i++)
	{	
		for(int i=1;i<=n;i++)p[i]=i;				//点的序号是从1开始,且并查集是对每个序号的点初始化,所以初始化时要从1-n ! 
		cnt=n-1;									//这个cnt是用来判断是否所有的点都被合并 
		for(int j=i;j<m;j++)
		{
			int R=r[j];
			//以下三行为并查集操作 
			int x=find(a[R]);int y=find(b[R]);
			if(x!=y)
			{
				p[x]=y;
				cnt--;
			}
			//合并成树以后,才能判断是否有最小的苗条度! 所以成不了树就不能比较最小值了,因为没有苗条度 
			if(!cnt)
			{
				ans=min(ans,w[R]-w[r[i]]);
				break;
			}
		}
	}
	return ans==0x3f3f3f3f?-1:ans;
}
int main()
{
	//freopen("input.txt", "r", stdin );
 	//freopen("output.txt", "w", stdout);
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		if(n==0&&m==0)break;
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&a[i],&b[i],&w[i]);
		}
		printf("%d\n",solve());
	}
	return 0;
 } 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值