天梯 畅通工程之局部最小花费问题
思路
kruskal算法求最小生成树。
因为如果已经有道路的话,那么这两个点算在一个集合中。剩下的,就求最小生成树就可以了。
代码
#include <bits/stdc++.h>
using namespace std;
#define all(x) std::begin(x), std::end(x)
struct edge {
int u, v, w;
edge(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {}
};
class DST {
private:
std::vector<int> dad;
int cnt;
public:
DST(int size) {
dad.assign(size + 1, -1);
cnt = size;
}
void init(int size) {
dad.assign(size + 1, -1);
cnt = size;
}
int& operator [] (int i) {
return dad[i];
}
int Find(int now) {
if (dad[now] > 0)
return dad[now] = Find(dad[now]);
return now;
}
bool Union(int a, int b) {
a = Find(a); b = Find(b);
if (a == b)
return false;
dad[a] += dad[b];
dad[b] = a;
cnt --;
return true;
}
const int count() const {
return cnt;
}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
cin >> n;
DST dst(n + 1);
vector<edge> ed;
int ans = 0;
for (int i = 0; i < (n - 1) * n / 2; ++ i) {
int u, v, w, d;
cin >> u >> v >> w >> d;
if (d == 1) {
dst.Union(u, v);
} else {
ed.push_back({u, v, w});
}
}
sort(ed.begin(), ed.end(), [](const edge &a, const edge &b) {
return a.w < b.w;
});
for (auto &[u, v, w] : ed) {
if (dst.Union(u, v)) {
ans += w;
}
}
cout << ans << '\n';
return 0;
}