AcWing 346. 走廊泼水节


题目思路
将一个最小生成树的图,添加一些边,使得成为一个完全图,并且生成的完全图的最小生成树还是原树
算法分析
构建最小生成树的Kruskal算法
- 首先将所有的边按照从小到大的顺序排序
- 对于一条边(x,y,w),如果x和y在不在一个连通块中,就说明他们之间没有边相连那么我们相连之后,现在这两个点,各自所在的连通块(集合),都拥有了一个最短边,也就是(x,y,w)
最小生成树已经确定了,那么原来两个连通块的其他点怎么办?
假设表示为之前所在的连通块,那么表示之前所在的连通块。
由于我们不能破坏最小生成树,所以我们原来这两个连通块必须具有如下性质:假设点A属于这个集合,点B属于这个集合,那么A与B之间的距离,必须大于之前的否者就会破坏之前的最小生成树,所以说
假如有个元素,然后有个元素,那么将和连通块中所有的点相连,就会增加:
每条边的最小长度为
所以就会得出
实现代码
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 6010;
struct Edge
{
int a, b, w;
bool operator < (const Edge & t)
{
return w < t.w;
}
}e[N];
int n;
int T;
int p[N], s[N];
int find(int x)
{
if(x != p[x]) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin >> T;
while(T --)
{
cin >> n;
for(int i = 0;i < n - 1;i++)
{
cin >> e[i].a >> e[i].b >> e[i].w;
}
sort(e, e + n - 1);
for(int i = 1;i <= n;i++) p[i] = i, s[i] = 1;
int res = 0;
for(int i = 0;i < n - 1;i++)
{
int a = find(e[i].a), b = find(e[i].b), w = e[i].w;
if(a != b)
{
p[a] = b;
res += (s[b] * s[a] - 1) * (w + 1);
s[b] += s[a];
}
}
cout << res << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 长文讲解 MCP 和案例实战
· Hangfire Redis 实现秒级定时任务,使用 CQRS 实现动态执行代码
· Android编译时动态插入代码原理与实践
· 解锁.NET 9性能优化黑科技:从内存管理到Web性能的最全指南
· 通过一个DEMO理解MCP(模型上下文协议)的生命周期
· 工良出品 | 长文讲解 MCP 和案例实战
· 多年后再做Web开发,AI帮大忙
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· centos停服,迁移centos7.3系统到新搭建的openEuler
· 上周热点回顾(4.14-4.20)