「暢通工程」是典型的最小生成樹(Minimum Spanning Tree,MST)問題。給定 N 個村莊(節點)及其兩兩之間的距離(邊權),目標是用最短的總公路長度連通所有村莊,即尋找圖的最小生成樹。
輸入:
3
1 2 1
1 3 2
2 3 4
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5
0
輸出:
3
5
邊:1-2(1), 1-3(2), 2-3(4)
MST 選擇 1-2 和 1-3,總長度 = 1 + 2 = 3
邊:1-2(1), 1-3(4), 1-4(1), 2-3(3), 2-4(2), 3-4(5)
MST 選擇 1-2(1), 1-4(1), 2-4(2) 或 1-2(1), 1-4(1), 2-3(3) → 最小為 1+1+2=4? 等等...
實際最優:1-2(1), 1-4(1), 2-4(2) 形成環,不可取。正確選擇:1-2(1), 1-4(1), 2-3(3) → 總長 5。樣例輸出 5 驗證正確。
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
const int MAXN = 105;
const int INF = INT_MAX;
int n;
int graph[MAXN][MAXN];
int dist[MAXN];
bool visited[MAXN];
int prim() {
fill(dist, dist + n + 1, INF);
fill(visited, visited + n + 1, false);
dist[1] = 0;
int total = 0;
for (int i = 1; i <= n; ++i) {
int u = -1, minDist = INF;
for (int j = 1; j <= n; ++j) {
if (!visited[j] && dist[j] < minDist) {
minDist = dist[j];
u = j;
}
}
if (u == -1) break; // 圖不連通
visited[u] = true;
total += minDist;
for (int v = 1; v <= n; ++v) {
if (!visited[v] && graph[u][v] < dist[v]) {
dist[v] = graph[u][v];
}
}
}
return total;
}
int main() {
while (cin >> n && n) {
fill(&graph[0][0], &graph[0][0] + MAXN * MAXN, INF);
int edges = n * (n - 1) / 2;
for (int i = 0; i < edges; ++i) {
int u, v, w;
cin >> u >> v >> w;
graph[u][v] = graph[v][u] = w;
}
cout << prim() << endl;
}
return 0;
}
這道題是圖論入門的經典必刷題,掌握 Prim 算法的矩陣實現是解決此類問題的關鍵。