首页 > 学院 > 开发设计 > 正文

kruskal算法

2019-11-11 05:13:35
字体:
来源:转载
供稿:网友
/*kruskal算法思想:每次选择图中最小边权的边,如果边两端的顶点在不同的连通块中,就把这条边加入最小生成树中。kruskal伪代码如下:int kruskal(){	令最小生成树的边权之和为ans、最小生成树的当前边数Num_Edge;	将所有边按边权从小到大排序;	for(从小到大枚举所有边)	{		if(当前测试边的两个端点在不同的连通块中)		{			将该测试边加入最小生成树中;			ans+=测试边的边权;			最小生成树的当前边数Num_Edge加1;			当边数Num_Edge等于顶点数减1时结束循环;		}	}	return ans;}*///kruskal算法应用实现代码#include<cstdio>#include<algorithm>using namespace std;const int MAXV = 110;const int MAXE = 10010;//边集定义部分struct edge{	int u, v;//边的两个端点编号	int cost;//边权}E[MAXE];//最多有MAXE边bool cmp(edge a, edge b){	return a.cost < b.cost;}//并查集部分int father[MAXV];//并查集数组/*int findFather(int x)//并查集查询函数{	int a = x;	while (x != father[x])	{		x = father[x];	}	//路径压缩	while (a != father[a])	{		int z = a;		a = father[a];		father[z] = x;	}	return x;}*/int findFather(int x)//递归版{	if (x == father[x])		return x;	else	{		int f = findFather(father[x]);		father[x] = f;		return f;	}}//kruskal部分,返回最小生成树的边权之和,参数n为顶点个数,m为图的边数int kruskal(int n, int m){	//ans为所求边权之和,Num_Edge为当前生成树的边数	int ans = 0, Num_Edge = 0;	for (int i = 0; i < n; i++)//顶点范围是[0,n-1]	{		father[i] = i;//并查集初始化	}	sort(E, E + m, cmp);//所有边按边权从小到大排序	for (int i = 0; i < m; i++)//枚举所有边	{		int faU = findFather(E[i].u);//查询测试边两个端点所在集合的根结点		int faV = findFather(E[i].v);		if (faU != faV)//如果不在一个集合中		{			father[faU] = faV;//合并集合(即把测试边加入最小生成树中)			ans += E[i].cost;//边权之和增加测试边的边权			Num_Edge++;//当前生成树的边数加1			if (Num_Edge == n - 1)break;//边数等于顶点数减1时结束算法		}	}	if (Num_Edge != n - 1)return -1;//无法连通时返回-1	else return ans;//返回最小生成树的边权之和}int main(){	int n, m;	scanf("%d%d", &n, &m);//顶点数,边数	for (int i = 0; i < m; i++)	{		scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].cost);//两个端点的编号、边权	}	int ans = kruskal(n, m);//kruskal算法入口	PRintf("%d/n", ans);	return 0;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表