ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

走廊泼水节 の t j

2022-07-29 16:01:02  阅读:126  来源: 互联网

标签:泼水节 连通 Sx Sy 最小 6005 走廊 生成


走廊泼水节

  给定一棵N个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小生成树仍然是这棵树。

求增加的边的权值总和最小是多少。

题目分析

  看到题面,我们首先需要知道完全图是什么。度娘如是说道:“完全图是一个简单的无向图,其中每对不同的顶点之间都恰连有一条边相连”。相当于题目给了你一颗子树,让你填充。倒着想,如果给了你一颗完全图求最小生成树,你会怎么求?先从小到大排序。然后你会发现对于最小生成树的每两个,如果在完全图中还存在另一边(最小生成树中不包含),那么这一边一定比对于这两点在最小生成树的任意边小。倒回来,你填充的任意边必须比这两点连通的边大。

首先我们设Sx表示为x之前所在的连通块 那么Sy表示为y之前所在的连通块.
假如说点A属于Sx这个集合之中 点B属于Sy这个集合之中.  那么点A与点B之间的距离,必须要大于之前的w,否则就会破坏之前的最小生成树,所以说(A,B)之间的距离最小为w+1。假如说我们知道Sx有p个元素,然后Sy有q个元素。那么将Sx与Sy连通块的所有点相连.显然这个两个连通块会增加.p×q−1条边。然后每一条边的最小长度都为w+1。

所以我们会得出
(w+1)×(p∗q−1)为两个连通块成为完全图的最小代价

 #include <bits/stdc++.h>
using namespace std;
int s[6005],fa[6005];
struct Edge {
	int u,v,w;
}edge[6005];
bool cmp (Edge x,Edge y) {
	return x.w<y.w;
}
int Find(int x) {
	if(fa[x]==x) return x;
	return fa[x]=Find(fa[x]);
}
int main() {
	int t;
	scanf("%d",&t);
	while(t--) {
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) 
			fa[i]=i,s[i]=1;
		for(int i=1;i<n;i++) {
			scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
		}
		sort(edge+1,edge+n,cmp);
		int ans=0;
		for(int i=1;i<n;i++) {
			int x=Find(edge[i].u),y=Find(edge[i].v);
			if(x==y) continue;
			fa[x]=y;
			ans+= (edge[i].w+1) * (s[x]*s[y]-1);
			s[y]+=s[x];
		}
		printf("%d\n",ans);
	}
	return 0;
}

 

标签:泼水节,连通,Sx,Sy,最小,6005,走廊,生成
来源: https://www.cnblogs.com/pangtuan666/p/16532540.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有