走廊泼水节
// 走廊泼水节.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
https://www.acwing.com/problem/content/348/
给定一棵 N 个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小生成树仍然是这棵树。
求增加的边的权值总和最小是多少。
注意: 树中的所有边权均为整数,且新加的所有边权也必须为整数。
输入格式
第一行包含整数 t,表示共有 t 组测试数据。
对于每组测试数据,第一行包含整数 N。
接下来 N−1 行,每行三个整数 X,Y,Z,表示 X 节点与 Y 节点之间存在一条边,长度为 Z。
输出格式
每组数据输出一个整数,表示权值总和最小值。
每个结果占一行。
数据范围
1≤N≤6000
1≤Z≤100
输入样例:
2
3
1 2 2
1 3 3
4
1 2 3
2 3 4
3 4 5
2
5
1 2 6
2 3 5
2 4 9
4 5 3
3
1 2 9
2 3 10
输出样例:
4
17
*/
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 6000 + 10;
int f[N];
long long setlen[N];
int n;
struct Edge {
int u, v, w;
bool operator<(const Edge& e) const {
return w < e.w;
}
}edges[N];
int T;
int find(int x) {
if (x != f[x]) f[x] = find(f[x]);
return f[x];
}
void init() {
for (int i = 0; i < N; i++) {
f[i] = i;
setlen[i] = 1;
}
}
void solve() {
cin >> n;
init();
for (int i = 0; i < n-1; i++) {
cin >> edges[i].u >> edges[i].v >> edges[i].w;
}
sort(edges,edges+n-1);
long long ans = 0;
for (int i = 0; i < n - 1; i++) {
int a = edges[i].u, b = edges[i].v, w = edges[i].w;
int fa = find(a), fb = find(b);
if (fa != fb) {
ans += (1ll*setlen[fa]*setlen[fb] -1) * (w + 1);
f[fa] = fb;
setlen[fb] += setlen[fa];
}
}
cout << ans << endl;
}
int main() {
cin >> T;
while (T--) {
solve();
}
return 0;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力

