最小生成树算法整理

                                       转载请注明出处:http://blog.youkuaiyun.com/wangjian8006

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图联通的最少的边。而最小生成树是使这些找到的最小的边权值之和达到最小。
最小生成树有两个算法:prim和kruskal
prim的思想是不段的找点
kruskal的思想是不断的找边
下面来介绍这两个算法
prim简单的描述下就是,在已知点集V中,找到所有V里面的点的邻边,首次保证相邻的点不在V里,取权值最小的边,再将相邻点加进V,这样不断的找,最后找到的n-1条边与n个顶点就是最小生成树。
其实prim和dijkstra的思想差不多,都是一个贪心的策略,只不过在更新条件上改成,取邻边里的最小边就可以了

 

void prim(){
	int i,j,v;
	int d[MAXV],vis[MAXV];
	for(i=1;i<=n;i++){
		d[i]=map[1][i];
		vis[i]=0;
	}
	
	for(i=1;i<=n;i++){
		int min=inf;
		for(j=1;j<=n;j++)
			if(!vis[j] && d[j]<min){			//找最小点加进来
				min=d[j];
				v=j;
			}
			
			vis[v]=1;
			
			for(j=1;j<=n;j++){
				if(!vis[j] && map[v][j]<d[j])		//取邻边的最小边
					d[j]=map[v][j];
			}
	}
	for(d[0]=0,i=1;i<=n;i++) d[0]+=d[i];
	printf("%d\n",d[0]);
}


kruskal
他是一个不断找边的过程,并且是一个贪心的思路,既然是贪心,那么肯定是从权值小的边开始往已知边集里面添加,首先要将边从小到大开始排序,然后从小到大试着将边往里面加,如果形成环我们就不加进来,如果不形成环就加进来,这样加到n-1条边为止,在判断是否有环,我们要用到并查集,因为kruskal的对象是边,所以适合稀疏图

 

#include <iostream>
using namespace std;
#define MAXM 15010
#define MAXV 1010

typedef struct{
	int s,t,w;
}Edge;

int n,m,set[MAXV];
Edge edge[MAXM];

int find(int x){
	int rt;
	if(set[x]!=x){
		rt=find(set[x]);
		set[x]=rt;
		return set[x];
	}else return x;
}

bool Union(int a,int b){
	int fa,fb;
	fa=find(a);
	fb=find(b);
	if(fa==fb) return 0;		//如果形成环就退出
	set[fa]=fb;
	return 1;
}

void kruskal(){
	int i,sum=0,cnt=0;
	for(i=1;i<=m;i++){
		if(Union(edge[i].s,edge[i].t)){
			sum+=edge[i].w;
			if(++cnt==(n-1)) break;			//找到n-1条边
		}
	}
	printf("%d\n",sum);
}

int cmp(const void * a,const void *b){
	return (*(Edge*)a).w-(*(Edge*)b).w;
}

int main(){
	int i;
	while(~scanf("%d%d",&n,&m)){
		for(i=0;i<=n;i++) set[i]=i;
		for(i=1;i<=m;i++){
			scanf("%d%d%d",&edge[i].s,&edge[i].t,&edge[i].w);
		}
		qsort(edge+1,m,sizeof(edge[0]),cmp);		//将边从小到大排序
		kruskal();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值