給定 n (≤ 100) 個村莊的鄰接矩陣 map[i][j] (距離),及 m 條**已建成道路** (權重視為 0)。求在現有基礎上**新增道路的最小總長度** 使所有村莊連通。多測試用例,EOF 結束。
m 條已有道路 (x,y),**將對應矩陣權重設為 0** (map[x-1][y-1] = map[y-1][x-1] = 0)。
#include
#include
#include
#define MAXN 101
#define INF 0x3f3f3f3f
int n;
int graph[MAXN][MAXN];
int minDist[MAXN];
int visited[MAXN];
void resetGraph(int n) {
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
scanf("%d", &graph[i][j]); // 直接讀入矩陣
int m; scanf("%d", &m);
for (int i = 0; i < m; ++i) {
int x, y; scanf("%d %d", &x, &y);
--x; --y; // 1-based -> 0-based
graph[x][y] = graph[y][x] = 0; // 已有路權重歸零
}
}
int prim(int n) {
for (int i = 0; i < n; ++i) {
minDist[i] = INF;
visited[i] = 0;
}
minDist[0] = 0;
int sum = 0;
for (int i = 0; i < n; ++i) {
int u = -1;
for (int j = 0; j < n; ++j)
if (!visited[j] && (u == -1 || minDist[j] < minDist[u]))
u = j;
visited[u] = 1;
sum += minDist[u];
for (int v = 0; v < n; ++v)
if (!visited[v] && graph[u][v] < minDist[v])
minDist[v] = graph[u][v];
}
return sum;
}
int main() {
while (scanf("%d", &n) == 1) {
resetGraph(n);
printf("%d\n", prim(n));
}
return 0;
}
| 技巧 | 說明 |
|---|---|
| 已有邊歸零 | 將已建道路權重設為 0,Prim 會優先選擇 0 邊,自動納入 MST 且不增加總成本 | 輸入格式 | 先給 n×n 矩陣,再給 m 及 m 行邊。注意下標轉換 (題目 1-based) |
| 對角線 | 題目矩陣對角線可能非 0,Prim 會自動忽略 (visited 機制),但建議讀入後 graph[i][i]=0 |
| 多測試用例 | while(scanf("%d",&n)==1) |
MST 性質:對於任意圖,給定某些邊**強制納入** (或權重設為 0),在剩餘邊中求 MST,等價於在修改權重後的圖上求標準 MST。因 0 權重邊必被貪心策略優先選中 (不構成環時),且不增加目標函數值。
O(n²) = 10⁴,極快。O(n²) 矩陣。