/************************ * * Author:Wang Yong * Blog:http://www.cnblogs.com/newwy * ************************/ #include <iostream> using namespace std; #define MAXN 10000 #define INF 10000000 //无向图最小生成树,prim算法,邻接阵形式,复杂度O(n^2) //返回最小生成树的长度,传入图的大小n和邻接阵mat,不相邻点边权inf //可更改边权的类型,pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1 //必须保证图的连通的! void Prim(int n,int Graph[][MAXN],int * pre) { int vset[MAXN],lowcost[MAXN];//lowcost[MAXN]表示存放顶点到为完成的生成树的最小权值 //v[MAXN]表示该结点是否已经在生成树里 int i,j,k; for(i = 0 ; i < n; i++) //赋初始值,将每个结点的连接到生成树的权值赋值为最大,所有结点均未在生成树中 //所有结点的前驱都是-1,表示没有任何结点与之相连 {lowcost[i] = INF;vset[i] = 0;pre[i] = -1;} for(lowcost[j = 0] = 0;j < n; j++)//分别将连通图中n个结点,加入到最小生成树中 { for(k = -1,i = 0; i < n; i++)//第一次循环将k 赋值 -1,这样找到第一个没有加入到生成树中的结点,之后k值改变 { //继续循环,寻找不在生成树中的结点到生成树的权值最小的那个结点,将其链接到生成树上 if(vset[i] == 0 &&(k == -1 || lowcost[i] < lowcost[k])) k = i; } printf("edge(%d,%d)的权值为%d,被加入生成树中\n",pre[k]+1,k+1,lowcost[k]); vset[k] = 1; //将选中的结点做好标记 for(i = 0 ; i < n; i++) //修正候选边,每次记录入选的结点k之后。分别记录其他结点到生成树的最小权值 { if(vset[i] == 0 && Graph[k][i] < lowcost[i]) { lowcost[i] = Graph[k][i]; pre[i] = k; //pre记录i结点到生成树最小权值是连接在k结点上 } } } } int mat[MAXN][MAXN],pre[MAXN]; int main() { memset(mat,INF,sizeof(mat)); int n; printf("请输入结点数目:"); scanf("%d",&n); int i,j; printf("输入边的数目:"); int en; scanf("%d",&en); int a,b,cost; for(i = 0 ; i < en ;i++) { scanf("%d %d %d",&a,&b,&cost); --a;--b; mat[a][b] = mat[b][a] = cost; } for(i = 0; i < n; i++) { for(j = 0 ; j < n ; j++) printf("%d ",mat[i][j]); printf("\n"); } Prim(n,mat,pre); }