洛谷【图论2-3】最小生成树 P1194 买礼物【C++解法】

题解思路:用到Kruskal最小生成树求法,题解在代码部分,废话不多说,上代码及题解:

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,M=510;

int a,b;//a代表初始每个礼物的价钱,b代表礼物个数 
int cnt;//记录边的个数 
int p[M];//并查集数组p,用于判断是否为同一集合 

//结构体用于存边 
struct st{
	int a,b,w;
}ed[N];

//重定义结构体排序,按边权值排序 
bool cmp(st a,st b)
{
	return a.w<b.w;
}

//并查集find函数, 
int find(int x)
{
	//路径压缩,让每个点直接指向根节点 
	if(p[x]!=x) p[x]=find(p[x]);
	return p[x];//返回根节点 
}

int main()
{
	cin>>a>>b;
	
	//初始化p数组,初始,每个元素都是一个集合,所以自己指向自己 ,记得从0到b [0,b],因为有0号节点 
	for(int i=0;i<=b;i++) p[i]=i;
	
	//将0号节点与其他所有节点建一条权值为a的边,也就对应,可以直接按原价格a元购买某一礼物 
	for(int i=1;i<=b;i++)
	{
		ed[cnt]={0,i,a};
		cnt++;	
	} 
	
	int x;
	for(int i=1;i<=b;i++)
	{
		for(int j=1;j<=b;j++)
		{
			cin>>x;
			//x==0时,代表没有优惠或是i==j没有意义,
			//i<j,是确保没有重边 
			if(x!=0 && i<j)
			{
				ed[cnt]={i,j,x};
				cnt++;
			}
		}
	}
	
	//排序 
	sort(ed,ed+cnt,cmp);
	
	//res记录最小生成树的值 
	int res=0;
	for(int i=0;i<cnt;i++)//总共cnt条边 
	{
		int a=ed[i].a,b=ed[i].b,w=ed[i].w;
		//如果find(a)!=find(b) ,表示a和b的根节点不一致,也就不在同一集合,就累加边权值
		//并将a和b集合合并,操作就是让a的根节点指向b的根节点 
		if(find(a)!=find(b))
		{
			res+=w;
			p[find(a)]=find(b);
		}
	}
	//输出答案 
	cout<<res;
	
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

#Dong#

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值