ybtoj最小生成树例题3公路建设
Posted SSL_ZZL
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj最小生成树例题3公路建设相关的知识,希望对你有一定的参考价值。
Link
解题思路
这题的数据是蛮水的,好像暴力最小生成树就可以过去
但是,你看着一条边一条边加的,暴力写完你心里真的不难受吗 (强迫症)
每输入两个点之间的新边,将旧边替换成新边,冒泡排序(插排也星)(不是错别字qwq)
再做最小生成树,复杂度
O
(
m
2
)
O(m^2)
O(m2)
我们考虑加入这条边对先前求出的生成树的影响,发现要么这条边插入生成树,并踢出原先生成树中的一条边,要么树没变,还是之前那棵树,没在最小生成树上的边在之后不会成为最小生成树上的边,将这些边全部忽略掉。每次kraskal复杂度变为O(n),总复杂度仅O(nm) ————一本通
反正就是看不懂啦
Code
#include <iostream>
#include <cstdio>
using namespace std;
struct DT{
int x, y, s;
}a[2100];
double ans;
int n, m, x, y, xx, yy, s, num, fa[510], p[510][510];
int find(int x) {
if (fa[x] == x) return x;
fa[x] = find(fa[x]);
return fa[x];
}
int main() {
scanf("%d %d", &n, &m);
for(int j = 1; j <= m; j++) {
scanf("%d %d %d", &x, &y, &s);
if (x > y)
swap(x, y);
//替换边
if (!p[x][y]) {
p[x][y] = ++num;
a[num] = (DT){x, y, s};
} else {
if (s > a[p[x][y]].s) {
if (ans == 0) printf("0\\n");
else printf("%0.1f\\n", ans / 2.0);
continue;
}
a[p[x][y]].s = s;
}
//冒泡排序
if (a[p[x][y]].s < s) {
for (int i = p[x][y]; i < num; i++)
if (a[i].s > a[i + 1].s) {
p[a[i].x][a[i].y] = i + 1;
p[a[i + 1].x][a[i + 1].y] = i;
swap(a[i], a[i + 1]);
} else break;
} else {
for (int i = p[x][y]; i > 1; i--)
if (a[i].s < a[i - 1].s) {
p[a[i].x][a[i].y] = i - 1;
p[a[i - 1].x][a[i - 1].y] = i;
swap(a[i], a[i - 1]);
}
}
//最小生成树
for (int i = 1; i <= n; i++)
fa[i] = i;
ans = 0;
for (int i = 1; i <= num; i++) {
xx = find(a[i].x), yy = find(a[i].y);
if (xx != yy) {
fa[xx] = yy;
ans += a[i].s;
}
}
//判答案
int flag = 0;
for (int i = 1; i <= n; i++)
if (fa[i] == i)
flag++;
if (flag > 1) ans = 0;
if (ans == 0) printf("0\\n");
else printf("%0.1f\\n", ans / 2.0);
}
}
以上是关于ybtoj最小生成树例题3公路建设的主要内容,如果未能解决你的问题,请参考以下文章
luogu P4513ybtoj线段树课堂过关例题3小白逛公园