【题解】「一本通 3.1 练习 2」构造完全图

网上这道题的题解似乎不多?虽然这是道水题,但是……还是记一记吧。非常啰嗦,有朝一日希望能做到言简意赅。

建议配合歌单食用:Prokofiev: Romeo and Juliet

题意

对于完全图G若有且仅有一棵最小生成树为T,则称完全图G是树T扩展出的。

给你一棵树T,找出T能扩展出的边权和最小的完全图G

思路

大佬言:当正向思维受阻时,逆向思维有奇效。

但是这是一道正向思维题,考察对算法的理解。(题目言简意赅,看起来不像过于复杂的题)

我们可以用递推的思想,考虑当我们有一个完全图G1时我们该怎么让这个图变大。显然,我们希望情况越简单越好,所以我们不直接连一个连通块,而往G1里加一个点u。这时我们要做的只是给uG1里的每一个点连上一条边。由于要满足T是最小生成树,因此,除题目中给出的T的、连接PG1的边d外,其它新增的边,边权都为d+1(扩展出的边权和最小)。

当题目涉及连通块时,可以考虑用并查集这一结构。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
int n;
int con[N],fa[N];//con记录连通块的规模 
struct edge{
	int s,t,d;
}e[N];
ll ans;

int findf(int x){
	con[x]=con[fa[x]];
	if(fa[x]!=x) return fa[x]=findf(fa[x]);
	return x;
}

bool cmp(edge x,edge y){
	return x.d<y.d;
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		scanf("%d%d%d",&e[i].s,&e[i].t,&e[i].d);
		con[i]=1;
		fa[i]=i;
	}
	con[n]=1;
	fa[n]=n;
	sort(e+1,e+n,cmp);
	for(int i=1;i<n;i++){
		int u=findf(e[i].s),v=findf(e[i].t);
		if(u!=v){
			ans+=(ll)(con[u]*con[v]-1)*(ll)(e[i].d+1)+(ll)e[i].d;
			con[u]+=con[v];
			con[v]=con[u];
			fa[u]=fa[v];
		}	
	}
	printf("%lld",ans);
	return 0;
}

你看,压根不用记起Kruskal这个名字。

posted @   Searshkiu  阅读(217)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示