hihoCoder#1097 最小生成树一·Prim算法
Prime算法,每次挑选一个距离原点最近的节点,然后收缩(visited为true,设置该点到原点的距离为0)
注意:虽然Prime算法跟Dijkstra很像,但两者还是不一样的。
因为Dijkstra算法每次在挑选节点后不会收缩,所以,用Dijkstra挑选的边并不一定是最小生成树。
比如下面这张图,有a、b、c三个节点
2 a----b \ | 3 \ | 2 \ | c
求a的单源最短路径得到的图是这样的:
2 a----b \ 3 \ \ c
而小生成树应该是这样的:
2 a----b | | 2 | c
代码:
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 #define MAX_POINT 1024 7 8 int N; 9 int g[MAX_POINT][MAX_POINT]; 10 bool visited[MAX_POINT]; 11 12 int prime() { 13 int res = 0; 14 int left = N - 1; 15 visited[1] = true; 16 while (left) { 17 int k = 0; 18 for (int i = 1; i <= N; i++) 19 if (!visited[i] && g[1][i] < g[1][k]) 20 k = i; 21 visited[k] = true; 22 left--; 23 res += g[1][k]; 24 g[1][k] = g[k][1] = 0; 25 for (int i = 1; i <= N; i++) 26 if (!visited[i] && g[1][i] > g[1][k] + g[k][i]) 27 g[1][i] = g[i][1] = g[1][k] + g[k][i]; 28 } 29 30 return res; 31 } 32 33 int main() { 34 memset(g, 1, sizeof(g)); 35 memset(visited, false, sizeof(visited)); 36 scanf("%d", &N); 37 for (int i = 1; i <= N; i++) 38 for (int j = 1; j <= N; j++) 39 scanf("%d", &(g[i][j])); 40 printf("%d\n", prime()); 41 42 return 0; 43 }