標準 MST 問題,但輸入中給出 m 條已建成的道路(必須保留)。求補全連通圖的最小額外代價。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 110;
const int MAXE = 10000;
struct Edge { int u, v, w; bool operator<(Edge o) const { return w < o.w; } };
Edge edges[MAXE];
int parent[MAXN];
bool built[MAXN][MAXN];
int dist[MAXN][MAXN];
int findSet(int x) { return parent[x]==x ? x : parent[x]=findSet(parent[x]); }
int main() {
int n;
while (scanf("%d", &n) == 1) {
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
scanf("%d", &dist[i][j]);
memset(built, 0, sizeof(built));
int m; scanf("%d", &m);
while (m--) { int x,y; scanf("%d%d",&x,&y); built[x][y]=built[y][x]=1; }
int ecnt = 0;
for (int i = 1; i <= n; ++i)
for (int j = i+1; j <= n; ++j)
edges[ecnt++] = {i, j, built[i][j] ? 0 : dist[i][j]};
sort(edges, edges+ecnt);
for (int i = 1; i <= n; ++i) parent[i] = i;
int ans = 0, cnt = 0;
for (int i = 0; i < ecnt && cnt < n-1; ++i) {
int u = edges[i].u, v = edges[i].v, w = edges[i].w;
int ru = findSet(u), rv = findSet(v);
if (ru != rv) {
parent[ru] = rv;
ans += w;
++cnt;
}
}
printf("%d\n", ans);
}
return 0;
}