//核心 Prim算法求最小生成树 /* 编一C程序,它能根据输入数据构造带权无向图G, 并输出G的最小生成树。 图的输入形式为n V0 Vi0 w0 V1 Vi1 w1 V2 Vi2 w2 ...Vi Vin wn -1 -1 -1(-1,-1,-1为输入结束标记,其余的值都>=0且<n),它们都是整数,且100>n>0。 */ #include <stdio.h> #define infinity 1000000 //常数infinity为无穷大 #define max_vertexes 100 //常数max_vertexes为图最大节点数 void prim(int G[][max_vertexes],int vcount,int father[]); int juZhen(int g[][max_vertexes]); void main() { int g[max_vertexes][max_vertexes]; int vcount=0,father[max_vertexes]; vcount=juZhen(g); //初始化矩阵 printf("该图的最小生成树为\n"); prim(g,vcount,father); } /* lowcost: 记录权值的 used[]: //记录每个顶点是否被并入:默认值为0;当并入后修改对应值为1 father[]: closeset[]: */ void prim(int G[][max_vertexes],int vcount,int father[]) { int i,j,k,m=0; int lowcost[max_vertexes],closeset[max_vertexes],used[max_vertexes]; int min; //初始化------------------------------------ for (i=0;i<vcount;i++) { used[i]=0; closeset[i]=0; father[i]=-1; } //------------------------------------------------ used[0]=1; //把第0个顶点归入集合u中 for(i=0;i<vcount;i++) { lowcost[i]=G[0][i]; //把各顶点到顶点0的权值保存在lowcost[i]中 } //---------------------------------------------------- for (i=1;i<vcount;i++) //循环次数:n个顶点,进行n-1次即可 ( u={v0}, 剩下的顶点{v1,.......} 开始生成最小生成树) { //求最小值 min=infinity; for(m=0;m<vcount;m++) { if(used[m]==0 && lowcost[m]<min) { min=lowcost[m]; j=m; } } father[j]=closeset[j]; //记录j的前领结点 used[j]=1; //把顶点j并入u中 for (k=0;k<vcount;k++) //新顶点并入u后重新选择最小边(针对lowcost[k]的修改) { if (!used[k]&&(G[j][k]<lowcost[k])) { lowcost[k]=G[j][k]; closeset[k]=j; } } } //自己加的:最小生成树的生成 for(m=0;m<vcount;m++) { if(father[m]!=-1) { printf("v%d-v%d\t",father[m],m); } } } int juZhen(int g[][max_vertexes]) { int vCount=0,i=0,j=0,w=0,m=0,n=0; printf("功能:依输入数据构造带权无向图G,并输出G的最小生成树\n\n"); printf("请输入图的顶点数,范围在1-%d\n",max_vertexes); //输入顶点个数 scanf("%d",&vCount); while(vCount<0 || vCount>max_vertexes) { printf("顶点个数输入有误,请重新输入"); scanf("%d",&vCount); } printf("则顶点的范围在0-%d\n",vCount-1); for(m=0;m<vCount;m++) //图的矩阵初始化 { for(n=0;n<vCount;n++) { g[m][n]=infinity; //默认权值为无穷大 } } printf("请输入图中边所连顶点i与j,及边的权值,以 -1 -1 -1为结束标志\n"); //图的矩阵 scanf("%d %d %d",&i,&j,&w); while(i!=-1 && j!=-1 && w!=-1) { //对顶点i j范围限制 if(i<0 ||i>=vCount || j<0 ||j>=vCount) { printf("顶点输入有误,请重新输入\n"); continue; } else { g[i][j]=w; g[j][i]=w; } scanf("%d %d %d",&i,&j,&w); } return vCount; }