假设V是图中顶点的集合,E是图中边的集合,TE为最小生成树中的边的集合,则prim算法通过以下步骤可以得到最小生成树:
1:初始化:U={u 0},TE={}。此步骤设立一个只有结点u 0的结点集U和一个空的边集TE作为最小生成树的初始行态,在随后的算法执行中,这个行态会不断的发生变化,直到得到最小生成树为止。
2:在所有u∈U,v∈V-U的边(u,v)∈E中,找一条权最小的边(u 0,v 0),将此边加进集合TE中,并将此边的非U中顶点加入U中。此步骤的功能是在边集E中找一条边,要求这条边满足以下条件:首先边的两个顶点要分别在顶点集合U和V-U中,其次边的权要最小。找到这条边以后,把这条边放到边集TE中,并把这条边上不在U中的那个顶点加入到U中。这一步骤在算法中应执行多次,每执行一次,集合TE和U都将发生变化,分别增加一条边和一个顶点,因此,TE和U是两个动态的集合,这一点在理解算法时要密切注意。
3:如果U=V,则算法结束;否则重复步骤2。可以把本步骤看成循环终止条件。我们可以算出当U=V时,步骤2共执行了n-1次(设n为图中顶点的数目),TE中也增加了n-1条边,这n-1条边就是需要求出的最小生成树的边。
O(∩_∩)O哈哈~发一个赤裸裸的求最小生成的题目(pku 1258)。以后比较复杂一点的最小生成树我再慢慢做。虽然这个最小生成树很简单,但我一直没有看,所以没有明白,今天终于看懂了~~~~
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 15966 | Accepted: 6494 |
Description
Input
Output
Sample Input
4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0
Sample Output
28
#includeusing namespace std; #define size 200 #define MAX 99999999 int array[size][size]; int Prim(int n) { int sum = 0,i,k,time=1; int low[size]; bool flag[size]; flag[0] = true; for(i = 1; i < n; i++) { low[i] = array[0][i]; flag[i] = false; } while(time<=n-1)//因为每循环一次找出一个点,所以只要循环n-1次一定能够把最小生成树找出来 { int min = MAX; int j = 0; for(k = 1; k < n; k++) if( low[k] < min && flag[k]==false )//找两个点之间的最短距离 { min = low[k]; j = k; } sum += min; flag[j] = true;//把找到的那个点加入到点集中 for(k = 1; k < n; k++) if(array[j][k] < low[k] && flag[k]==false) low[k] = array[j][k]; time++; } return sum; } int main() { int num,i; while(cin>>num) { for(i = 0; i < num; i++) for(int j = 0; j < num; j++) cin>>array[i][j]; cout<