最小生成树破圈法C语言版本

最小生成树破圈法 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相连

参考: 华沙尔算法

c++代码优化

  • 12
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值