题目大意:
题解:
在已有图中添加一个点,表示地下天然水源,该点与其他各点之间建立一条权值为打井费用的边,在某一点打井相当于选择该点与地下水源之间的边,然后跑最小生成树即可。
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
int n, fa[310], cnt;
struct Edge {
int u, v, w;
bool operator<(const Edge &obj) const { return w < obj.w; }
} edge[45310];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
int kruscal() {
int ans = 0;
for (int i = 0; i <= n; ++i) {
fa[i] = i;
}
int tot = 0;
for (int i = 1; i <= cnt; ++i) {
int u = edge[i].u, v = edge[i].v;
int fau = find(u), fav = find(v);
if (fau != fav) {
fa[fau] = fav;
tot++;
ans += edge[i].w;
if (tot == n) {
return ans;
}
}
}
}
int main() {
while (scanf("%d", &n) == 1) {
cnt = 0;
for (int i = 1; i <= n; ++i) {
edge[++cnt].u = 0;
edge[cnt].v = i;
scanf("%d", &edge[cnt].w);
}
for (int i = 1, w; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
scanf("%d", &w);
if (i < j) {
edge[++cnt].u = i;
edge[cnt].v = j;
edge[cnt].w = w;
}
}
}
sort(edge + 1, edge + cnt + 1);
printf("%d\n", kruscal());
}
return 0;
}