【ybtoj 高效进阶 3.2】【最小生成树】 构造完全图

【ybtoj 高效进阶 3.2】【最小生成树】 构造完全图

题目

在这里插入图片描述
在这里插入图片描述


解题思路

最小生成树就是在一个完全图里找到能使所有点相连且边权最小
那么最小生成树中的一条边可以看作是连接两个大小为V1,V2的连通块中最短的边
而完全图是所有节点都两两相连
那么还需要连V1*V2-1条边
为了边权最小且都大于最小生成树中的那一边d
我们将ta视为d+1

按边权大小排序
查找每条边连接的点是否在同一集合
不是就补边累计答案
且合并两个集合
感觉像并查集了
(⊙_⊙)?


代码

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
struct lzf{
	int x,y,q;
}a[100100];
long long n,tot,fa[100010],num[100010];
bool cmp(lzf f,lzf y)
{ 
     return f.q<y.q;
}
int find(int w)
{
	if (fa[w]==w) return w;
	   else return fa[w]=find(fa[w]);
}
int main()
{
	scanf("%lld",&n);
	for (int i=1;i<n;i++)
	    scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].q);
	for (int i=1;i<=n;i++) fa[i]=i,num[i]=1;
	sort(a+1,a+n,cmp);  //按边权排序
	for (int i=1;i<n;i++)
	{
		int xx=find(a[i].x),yy=find(a[i].y);
		if (xx!=yy)
		{
		   fa[xx]=yy;  //合并
		   tot+=(num[xx]*num[yy]-1)*(a[i].q+1)+a[i].q;   //累计答案,不要忘记加最小生成树中的那一边
		   num[yy]+=num[xx];  //集合元素增加
		}
	}
	printf("%lld",tot);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值