最小生成树破圈法 C语言版本
code
#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 16 /*顶点的最大个数*/
int NUMS;
int E_NUMS;
int edg_flag,am,p,q;
typedef char VexType; /*顶点的数据类型*/
typedef int AdjType; /*邻接矩阵的数据元素的类型*/
typedef struct
{
VexType vexs[MAXVEX]; //顶点
AdjType arcs[MAXVEX][MAXVEX]; //边
int n; //记录当前图的顶点数
}GraphMatrix;
GraphMatrix* CreateGraph(void) //创建无向带权图
{
int i,j,k,e,m;
GraphMatrix *ga;
ga=(GraphMatrix *)malloc(sizeof(GraphMatrix));
printf("请输入顶点的个数(不超过%d):",MAXVEX);
scanf("%d",&(ga->n));
getchar();
NUMS = ga->n;
printf("请顺序地输入各顶点的信息(序号即可,用一个字符表示):\n");
for(i=0; i<ga->n; i++)
ga->vexs[i]=getchar(); /*读入顶点信息,建立顶点表*/
getchar();
for(i=0; i<ga->n; i++)
for(j=0; j<ga->n; j++)
ga->arcs[i][j]=0; /*邻接矩阵初始化*/
printf("请输入边的个数:");
scanf("%d",&e);
E_NUMS = e;
printf("请输入与边相关联的两个顶点的序号:\n");
for(k=0;k<e;k++)
{
scanf("%d%d%d",&i,&j,&m); /*读入边以及权值*/
ga->arcs[i][j]=m;
ga->arcs[j][i]=m;
}
getchar();
return ga;
}
void PrintGraph(GraphMatrix *ga)
{
int i,j;
printf("\n顶点表为:\n");
for(i=0; i<ga->n; i++)
printf("%4c",ga->vexs[i]);
printf("\n邻接矩阵为:\n");
for(i=0; i<ga->n; i++)
{
for(j=0; j<ga->n; j++)
printf("%4d",ga->arcs[i][j]);
printf("\n");
}
}
int Wshall(int array[MAXVEX][MAXVEX]) {
int i,j,k,m=0,n=NUMS;
// printf("\n---test---\n");
// for(i=0;i<NUMS;i++) {
// for(j=0;j<NUMS;j++) {
// printf(" %d",array[i][j]);
// }
// printf("\n");
// }
// printf("\n");
//
int r[n][n],B[n][n];
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
r[i][j]=0;
B[i][j]=array[i][j];
//分界线
if(array[i][j]>=1)
B[i][j]=1;
else
B[i][j]=0;
//分界线
}
}
for(j=0;j<n;j++)
{
for(i=0;i<n;i++)
if(B[i][j]>=1)
{
for(k=0;k<n;k++)
{
if(B[k][i]>=1)
{
B[k][j]=B[j][k]=1;
}
}
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
if(!B[i][j])
{
return 0;
}
}
return 1;
}
void break_circle(GraphMatrix *gh) {
int i,j,flag[MAXVEX];
int am = 10000;
for(i=0; i<gh->n; i++)
{
flag[i]=0; //标记每个顶点都为没有访问
}
int edg_flag;
int p=-1,q=-1;
while(E_NUMS>NUMS-1)
{
int ptm,qtm;
int max;
max = 0;
for(i=0;i<NUMS;i++)
{
for(j=i;j<NUMS;j++)
if((gh->arcs[i][j]>max)&&(gh->arcs[i][j]<=am)&&((i!=p)||(j!=q)))
{
max = gh->arcs[i][j];
ptm = i;
qtm = j;
}
}
am = max;
printf("max=%5d\t",am);
p = ptm;
q = qtm;
gh->arcs[p][q]=0;
gh->arcs[q][p]=0;
edg_flag = Wshall(gh->arcs);//华沙尔算法判断是否连通
printf("\nflag= %d\n",edg_flag);
if(edg_flag==1)
{
E_NUMS=E_NUMS-1;
//printf("flag= %d",flag);
}
else
{
gh->arcs[p][q]=am;
gh->arcs[q][p]=am;
}
}
//输出破圈后的 邻接矩阵
printf("\n");
printf("最小生成树的邻接矩阵为:\n");
for(i=0; i<gh->n; i++)
{
for(j=0; j<gh->n; j++)
printf("%4d",gh->arcs[i][j]);
printf("\n");
}
printf("最小生成树的为:\n");
for(i=0; i<gh->n; i++)
{
for(j=0; j<=i; j++) {
if(gh->arcs[i][j] > 0) {
printf("%c和%c相连\n",gh->vexs[j],gh->vexs[i]);
}
}
}
}
//主函数
int main()
{
GraphMatrix *graph;
graph = CreateGraph();
PrintGraph(graph);
printf("\n");
break_circle(graph);
return 0;
}
测试用例1:
请输入顶点的个数(不超过16):6
请顺序地输入各顶点的信息(从0起):
012345
请输入边的个数:8
请输入与边相关联的两个顶点的序号:
0 1 1
0 2 5
0 3 2
1 4 7
1 2 3
2 5 6
3 5 8
4 5 4
示例1输出:
顶点表为:
0 1 2 3 4 5
邻接矩阵为:
0 1 5 2 0 0
1 0 3 0 7 0
5 3 0 0 0 6
2 0 0 0 0 8
0 7 0 0 0 4
0 0 6 8 4 0
max= 8
flag= 1
max= 7
flag= 1
max= 6
flag= 0
max= 5
flag= 1
最小生成树的邻接矩阵为:
0 1 0 2 0 0
1 0 3 0 0 0
0 3 0 0 0 6
2 0 0 0 0 0
0 0 0 0 0 4
0 0 6 0 4 0
最小生成树的为:
0和1相连
1和2相连
0和3相连
2和5相连
4和5相连
测试用例2:
请输入顶点的个数(不超过16):7
请顺序地输入各顶点的信息(序号即可,用一个字符表示):
SABCDET
请输入边的个数:12
请输入与边相关联的两个顶点的序号:
0 1 2
0 2 5
0 3 4
1 2 2
1 4 7
2 3 1
2 4 5
2 5 3
3 5 4
4 5 1
4 6 5
5 6 7
示例2输出:
顶点表为:
0 1 2 3 4 5 6
邻接矩阵为:
0 2 5 4 0 0 0
2 0 2 0 7 0 0
5 2 0 1 5 3 0
4 0 1 0 0 4 0
0 7 5 0 0 1 5
0 0 3 4 1 0 7
0 0 0 0 5 7 0
max= 7
flag= 1
max= 7
flag= 1
max= 5
flag= 1
max= 5
flag= 1
max= 5
flag= 0
max= 4
flag= 1
max= 4
flag= 1
最小生成树的邻接矩阵为:
0 2 0 0 0 0 0
2 0 2 0 0 0 0
0 2 0 1 0 3 0
0 0 1 0 0 0 0
0 0 0 0 0 1 5
0 0 3 0 1 0 0
0 0 0 0 5 0 0
最小生成树的为:
S和A相连
A和B相连
B和C相连
B和E相连
D和E相连
D和T相连
参考: 华沙尔算法