Kerry 的电缆网络——kruskal算法

Description

Kerry 是德国的一位电缆商人。因联合国脱贫计划的邀请,他准备负责在土鲁齐亚埃萨亚克斯乌托斯邦建立电缆网络,以满足这个国家的用电需求。当然,现在土鲁齐亚埃萨亚克斯乌托斯邦没有任何电缆。已知土鲁齐亚埃萨亚克斯乌托斯邦一共有n个城镇,已经编号为1到n。其中任意两个城镇可能有一条路,也可能没有。如果两个城镇之间有一条路pi,那么这条路有一个长度si,则Kerry可以在这两个城市之间建立一条电缆线,电缆线的长度也就是这条路的长度si。

现在Kerry准备了s长的电缆线,电缆线可以任意拆断,拆断不损失任何电缆线。他需要将土鲁齐亚埃萨亚克斯乌托斯邦所有城镇都能够连入这个电缆网络。那么,Kenny能不能使用这s长度的电缆线完成这项工作;如果能够完成,那么Kerry最少耗用多少长度的电缆线呢?
Input

第一行一个正实数S;

第二行一个正整数n;

接下来一共有m行(m是个未知数),第i行有两个整数xi,yi和一个实数si,表示编号为xi个村庄和编号为yi个村庄之间有一条路,路的长度为si。

输入保证xi不等于yi,两个城镇之间不会有两条路。
Output

若能够完成(建立这样的电缆网络),则输出(其中代表最少的电缆线长度,保留两位小数):

Needmiles of cable

否则输出:

Impossible

Sample Input

100.0
4
1 2 2.0
1 3 4.2
1 4 6.7
3 4 4.0
2 4 10.0
Sample Output
Need 10.20 miles of cable

HINT

1<=n,m<=100000

分析

最小生成树—kruskal算法+并查集

将边权从小到大排序,依次将权值最小的边加入最小生成树中(也叫加边法),用并查集判断是否构成环。当边数=顶点数-1时,所有顶点(城市)已经在最小生成树,也就是电缆网络中。最后判断所需最小长度是否大于s,如果在范围内,按题目要求输出;如果不在,输出Impossible

代码
#include<cstdio>
#include<iostream> 
#include<algorithm>
using namespace std;
double mincost,cost,s1;
int f[100010],s,t,j,n,ans;
int find(int x){
	if(f[x]==x)return x;
	return f[x]=find(f[x]);//路径压缩 
}
struct Edge{
	int a,b;
	double w;
}edge[100010];
bool cmp(Edge a,Edge b){
    return a.w<b.w;
}
int main(){
	scanf("%lf%d",&s1,&n);
	while(scanf("%d%d%lf",&s,&t,&cost)!=EOF){
		j++;
		edge[j]={s,t,cost};
	}
	sort(edge+1,edge+1+j,cmp);//边权从大到小排序 
	for(int i=1;i<=n;i++){
		f[i]=i;
	}
	for(int i=1;i<=j;i++){
		
		int fx=find(edge[i].a);
		int fy=find(edge[i].b);
		if(fx!=fy){//用并查集判断顶点是否已经在最小生成树中,也就是判断是否构成环 
			ans++;
			mincost+=edge[i].w;
			f[fx]=fy;
		}
		if(ans==n-1) break;//所有顶点已经在最小生成树中 
	}
	if(mincost<=s1&&ans==n-1){//判断 
		printf("Need %.2lf miles of cable",mincost);
	}else{
		cout<<"Impossible"<<endl;
	}
	
	
	return 0;
} 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值