【题解】「一本通 3.1 练习 2」构造完全图
网上这道题的题解似乎不多?虽然这是道水题,但是……还是记一记吧。非常啰嗦,有朝一日希望能做到言简意赅。
建议配合歌单食用:Prokofiev: Romeo and Juliet
题意
对于完全图若有且仅有一棵最小生成树为,则称完全图是树扩展出的。
给你一棵树,找出能扩展出的边权和最小的完全图。
思路
大佬言:当正向思维受阻时,逆向思维有奇效。
但是这是一道正向思维题,考察对算法的理解。(题目言简意赅,看起来不像过于复杂的题)
我们可以用递推的思想,考虑当我们有一个完全图时我们该怎么让这个图变大。显然,我们希望情况越简单越好,所以我们不直接连一个连通块,而往里加一个点。这时我们要做的只是给和里的每一个点连上一条边。由于要满足是最小生成树,因此,除题目中给出的的、连接和的边外,其它新增的边,边权都为(扩展出的边权和最小)。
当题目涉及连通块时,可以考虑用并查集这一结构。
代码
#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;
}
你看,压根不用记起这个名字。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!