最小生成树(二)-----Kruskal算法

最小生成树Kruskal算法:

先来说一下Kruskal算法的步骤:

1.建图,存储图中每条边的信息(start,end,cost:起点,终点,权值)

2.将图中各边按照权值由小到大排列

3.选取当前权值最小的边,如果该边的start,end,分别在两个不同的联通分量中,则加入该边

4.重复3.  直到所有点在同一个连通分量中


由步骤可以看出Kruskal算法的时间消耗主要用在排序上,所以在稀疏图中Kruskal算法有一定的优势

在这个算法中还用到并查集的知识,用于判断start,end是否在同一连通分量中

所以先来

并查集:

int Pre[MAX],Rank[MAX];		//Pre用来存储每个点的父亲,Rank则对应树的高度 
void Init(){
	for(int i=0;i<=N;i++){//初始化 
		Pre[i]=i;
		Rank[i]=1;
	}
}
int Find(int x){		//路径压缩,寻找父节点 
	return Pre[x]==x ? x: Pre[x]=Find(Pre[x]);
}
void Unite(int a,int b){
	int x=Find(a);
	int y=Find(b);
	if(x!=y){			//如果a,b两点的父亲节点不同,合并 
		if(Rank[x]>Rank[y]){
			Pre[y]=x;
			Rank[x]+=Rank[y];
		}
		else {
			Pre[x]=y;
			Rank[y]+=Rank[x];
		}
	}
}
int Same(int a,int b){//判断a,b是否属于同一父节点 
	return Find(a)==Find(b);
}
Kruskal算法:

struct edge{		//定义边的结构体 
	int start,end;
	double cost;
};
edge Edge[MAX];		//MAX表示最大变的数量 
bool comp(const edge &a, const edge &b){  //自定义排序函数 ,按cost值由小到大排列 
	return a.cost<b.cost;
}
int Pre[MAX],Rank[MAX];		//Pre用来存储每个点的父亲,Rank则对应树的高度 

double Kruskal(){
	sort(Edge,Edge+cont,comp);		//排序 
	Init();						//并查集初始化 
	double sum=0;		//最小生成树长度 
	for(int i=0;i<cont;i++){	//按cost从小到大选取 
		edge tempE=Edge[i];
		if(!Same(tempE.start,tempE.end)){	//该边的起始点,跟终点不在同一连通分量 
			sum+=tempE.cost;			//sum+cost 
			Unite(tempE.start,tempE.end);//合并 
		} 
	}
	return sum;
}

如有异议欢迎指正,谢谢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值