[Sicily 1090 Highways] 求最小生成樹的兩種演算法(普里姆演算法/克魯斯卡爾演算法)
阿新 • • 發佈:2019-01-27
(1)問題描述:
政府建公路把所有城市聯絡起來,使得公路最長的邊最短,輸出這個最長的邊。
(2)基本思路:
使得公路最長的邊最短其實就是要求最小生成樹。
(3)程式碼實現:
普里姆演算法:
#include <iostream> using namespace std; #define MAX_DIS 1000000 int main() { int T; cin >> T; for(int t = 1; t <= T; t++) { int n; cin >> n; int mat[n + 1][n + 1]; int d[n + 1]; int v[n + 1]; for(int i = 1; i <= n; i++) { fill(mat[i], mat[i] + n + 1, MAX_DIS); } for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { cin >> mat[i][j]; } } int max_length = 0; fill(d, d + n + 1, MAX_DIS); fill(v, v + n + 1, 0); d[1] = 0; for(int i = 1; i <= n; i++) { int min = MAX_DIS; int min_index = -1; for(int j = 1; j <= n; j++) { if(d[j] < min && v[j] == 0) { min = d[j]; min_index = j; } } //加入點min_index v[min_index] = 1; if(min > max_length) max_length = min; for(int j = 1; j <= n; j++) { if(v[j] == 0 && mat[min_index][j] < d[j]) { d[j] = mat[min_index][j]; } } } cout << max_length << endl; if(t != T) cout << endl; } return 0; }
克魯斯卡爾演算法:
#include <iostream> #include <algorithm> using namespace std; int u[200000];//左端點 int v[200000];//右端點 int w[200000];//權重 int e[200000];//輔助排序,排完序後,e[0]所存的值是使得權重w[e[0]]最小的 int p[501];//並查集 bool cmp(int i, int j) { return w[i] < w[j]; } int find(int x) { return (p[x] == -1)? x: p[x] = find(p[x]); } int _union(int x, int y) { p[y] = x; } int main() { int T; cin >> T; for(int t = 1; t <= T; t++) { int n; cin >> n; int count = 0;//表示一共有幾條邊 int weight; for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { cin >> weight; if(weight != 0) { if(i < j)//只需要存其中一條邊 { u[count] = i; v[count] = j; w[count] = weight; count++; } } } } //思想:把邊排序 for(int i = 0; i < count; i++) e[i] = i; sort(e, e + count, cmp); //並查集初始化每個點的根結點為自己(-1) for(int i = 1; i <= n; i++) p[i] = -1; int min_w_index; int x; int y; int edge = 0; for(int i = 0; i < count; i++) { min_w_index = e[i]; x = find(u[min_w_index]); y = find(v[min_w_index]); //若左端點和右端點的根結點一樣,則加入的邊必然導致環 if(find(x) != find(y))//根結點不同的時候加入 { edge++; _union(x, y); } if(edge == n - 1) { cout << w[min_w_index] << endl; break; } } if(t != T) cout << endl; } }