公路建设
题目链接:ybt高效进阶3-2-3
题目大意
有一些点,每次会加一个边,每次加完边都问你最小生成树的值的一半是多少。
如果无法连通就输出
0
0
0,一开始没有边。
思路
其实这道题就是每次多加一条边都跑一次最小生成树。
记得初始化和判断无法连通的情况就可以了,而且输出的是答案除以 2 2 2 这个不要忘了。
(stm 我一开始还以为要 LCA 剪边一顿乱搞的,结果算算时间复杂度跟直接暴力跑最小生成树差不多,还很麻烦)
代码
#include<cstdio>
#include<algorithm>
using namespace std;
struct node {
int x, y;
long long z;
}a[2001], b[2001];
int n, m, fa[501], num;
long long ans;
int find(int now) {
if (fa[now] == now) return now;
return fa[now] = find(fa[now]);
}
bool cmp(node x, node y) {
return x.z < y.z;
}
int main() {
scanf("%d %d", &n, &m);
for (int times = 1; times <= m; times++) {
scanf("%d %d %lld", &a[times].x, &a[times].y, &a[times].z);
for (int i = 1; i <= times; i++) b[i] = a[i];
for (int i = 1; i <= n; i++) fa[i] = i;
sort(b + 1, b + times + 1, cmp);
if (times < n - 1) {
printf("0\n");
continue;
}
num = 0;
ans = 0;
for (int i = 1; i <= times; i++) {//正常跑最小生成树
int X = find(b[i].x), Y = find(b[i].y);
if (X == Y) continue;
fa[X] = Y;
num++;
ans += b[i].z;
if (num == n - 1) break;
}
if (num < n - 1) {
printf("0\n");
continue;
}
if (ans & 1) printf("%d.5\n", ans >> 1);
else printf("%d.0\n", ans >> 1);
}
return 0;
}