不相交集应用--kruskal算法

【问题描述】
 已知含有n个顶点的带权连通无向图,采用邻接矩阵存储,邻接矩阵以三元组的形式给出,只给出不包括主对角线元素在内的下三角形部分的元素,且不包括不相邻的顶点对。分别采用prim算法和kruskal算法,求该连通图的最小生成树的权值之和。
【输入形式】
 第一行给出结点个数n和三元组的个数count,以下每行给出一个三元组,数之间用空格隔开。(注意这里顶点的序号是从1到n,而不是0到n-1,程序里要小心!)
【输出形式】
 两种算法求解的最小生成树的权值之和
【样例输入】
 5 8
 2 1 7
 3 1 6
 3 2 8
 4 1 9
 4 2 4
 4 3 6
 5 2 4
 5 4 2
【样例输出】

18

18

 

//Kruskal 算法 

typedef struct
{
	int begin;
	int end;   //储存边的头尾和权值 
	int weight;
}Edge;

Edge edge[MAX_VERTEX_NUM];

void Sort(Graph &G)  //找出最小权值 
{
	int i,j;
	Edge temp;
   for(i=0;i<=G.arcnum-2;i++)
   for(j=0;j<=G.arcnum-i-2;j++)
     if(edge[j].weight>edge[j+1].weight)   
        {
           temp=edge[j];
          edge[j]=edge[j+1];
          edge[j+1]=temp;
}


}

int p[MAX_VERTEX_NUM];//定义点的集合 
int rank[MAX_VERTEX_NUM];

int Find(int x)//查找集合i(一个元素是一个集合)的源头(递归实现)
{
	int y=x;
	while(p[y]!=y)
	{
		y=p[y];
	}
	int root=y;
	y=x;
	while(p[y]!=y)
	{
		int w=p[y];
		p[y]=root;
		y=w;
	}
	return root;
}

void Union(int x,int y)//加入团体
{
	int u=Find(x);
	int v=Find(y);
	if(rank[u]<=rank[v])
	{
		p[u]=v;
		if(rank[u]==rank[v])
		rank[v]++;
	}
}


int  MiniSpanTree_Kruskal(Graph &G)
{
	int i,j,k=0,sum=0;
	for(i=0;i<G.vexnum;i++)//初始化点的集合.刚开始每个点互相独立,自己是自己的上级 
	{
       p[i]=i;
       rank[i]=0;
	}

	for(i=0;i<G.vexnum;i++)//把边储存
	{
		for(j=0;j<G.vexnum;j++)
		{
			if(G.arcs[i][j].adj!=INFINITY&&i<j) 
			{
				edge[k].begin=i;
				edge[k].end=j;
				edge[k].weight=G.arcs[i][j].adj;
				k++;
			}

		}
	}
    Sort(G);//边的权值排序
    k=0;
    for(i=0;i<G.arcnum,k<G.vexnum-1;i++)//n个点加入n-1条边 
    {   
    	if(Find(edge[i].begin)!=Find(edge[i].end))//假如begin和end上级不一样也就是不在一个团体 
		{
			Union(edge[i].begin,edge[i].end);//加入 
			sum+=edge[i].weight; 
			k++;//已连接边数+1 
		}
	}
	
	return sum;
}


 

int main()
{
	Graph G;
	CreateMatrix(&G);
    cout<<MiniSpanTree_Prim(G,1)<<endl;
    cout<<MiniSpanTree_Kruskal(G);

}
 
 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值