有n个城市,其中k个城市有发电站,给出每个城市之间连接电线的花费,要求使每个城市通电的最小花费。
维护并查集用kruskal算法解决MST问题,标记每个发电站,在连边时取发电站为代表元素连边,连边时要判断两个城市的父节点是否是两个不同的发电站。
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 100 + 5;
struct edge {
int from, to, cost;
bool operator < (const edge &e) const {
return cost < e.cost;
}
};
int mark[maxn];
int d[maxn][maxn];
vector<edge> v;
int par[maxn];
void init(int n) {
for (int i = 0; i < n; i++) {
par[i] = i;
}
}
int find(int x) {
if (par[x] == x) {
return x;
} else {
return par[x] = find(par[x]);
}
}
void unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return;
}
if (mark[x]) {
par[y] = x;
} else {
par[x] = y;
}
}
bool same(int x, int y) {
return find(x) == find(y);
}
int main(int argc, char const *argv[]) {
int n, k;
scanf("%d%d", &n, &k);
for (int i = 0; i < k; i++) {
int v;
scanf("%d", &v);
mark[--v] = 1;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &d[i][j]);
}
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (mark[i] && mark[j]) {
continue;
}
v.push_back((edge){i, j, d[i][j]});
}
}
sort(v.begin(), v.end());
int ans = 0;
init(n);
for (int i = 0; i < v.size(); i++) {
edge &e = v[i];
int u = e.from, v = e.to;
if (!same(u, v)) {
if (mark[find(u)] != 1 || mark[find(v)] != 1) {
unite(u, v);
ans += e.cost;
}
}
}
printf("%d\n", ans);
return 0;
}