最小生成树算法--并查集实现

24 篇文章 1 订阅
7 篇文章 0 订阅

第一行有两个数,n和m,n表示有n个顶点,m表示有m条边,接下来m行,没行行如a b c,

用来表示一条边,意思是从顶点a到顶点b的权值为c。

求最小生成树

输入数据:

6  9

2 4 11

3 5 13

4 6 3

5 6 4

2 3 6

4 5 7

1 2 1

3 4 9

1 3 2

运行结果:19



主要的代码实现:


<span style="font-size:18px;">//通过并查集实现最小生成树 
#include<stdio.h>
//为了方便排序,这里创建一个结构体用来存储边的关系 
struct edge
{
	int u;
	int v;
	int w;
};
struct edge e[10];//数组大小根据实际情况来设置,要比m的最大值大1 
int n,m;
int f[7]={0},sum=0,count=0;//并查集需要用到的一些变量 
//f数组大小根据实际情况来设置,要比n的最大值大1 
//快速排序 
void quicksort(int left,int right)
{
	int i,j;
	struct edge t;
	if(left>right)
	{
		return ;
	}
	i=left;
	j=right;
	while(i!=j)
	{
		//顺序很重要,要先从右边开始找 
		while(e[j].w>=e[left].w&&i<j)
		{
			j--;
		}
		//再从左边开始找 
		while(e[i].w<=e[left].w&&i<j)
		{
			i++;
		}
		//交换 
		if(i<j)
		{
			t=e[i];
			e[i]=e[j];
			e[j]=t;
		}
	}
	//最终将基准数归位,将left和i互换 
	t=e[left];
	e[left]=e[i];
	e[i]=t;
	//继续处理左边的,这里是一个递归的过程 
	quicksort(left,i-1);
	//继续处理右边的,这里是一个递归的过程 
	quicksort(i+1,right);
	return ;
}
//并查集寻找祖先的函数 
int getf(int v)
{
	if(f[v]==v)
	{
		return v;
	}
	else
	{
		//这里是路径压缩 
		f[v]=getf(f[v]);
		return f[v];
	}
}
//并查集合并两个集合的函数 
int merge(int v,int u)
{
	int t1,t2;
	t1=getf(v);
	t2=getf(u);
	//判断两个点是否在同一个集合中 
	if(t1!=t2)
	{
		f[t2]=t1;
		return 1;
	}
	return 0;
}
int main(void)
{
	int i;
	//读入n和m,n表示顶点个数,m表示边的条数 
	scanf("%d %d",&n,&m);
	//读入边,这里用一个结构体来存储边的关系 
	for(i=1;i<=m;i++)
	{
		scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
	}
	//按照权值从小到大对边进行快速排序 
	quicksort(1,m);
	//并查集初始化 
	for(i=1;i<=n;i++)
	{
		f[i]=i;
	}
	//Kruskal算法核心部分 
	for(i=1;i<=m;i++)//开始从小到大枚举每一条边 
	{
		//判断一条边的两个顶点是否已经连通,即判断是否在同一个集合中 
		if(merge(e[i].u,e[i].v))//如果目前尚未连通,则选用这条边 
		{
			count++;
			sum=sum+e[i].w;
		}
		//直到选用了n-1条边之后退出循环 
		if(count==n-1)
		{
			break;
		}		
	}
	printf("%d\n",sum);
    return 0;
 } </span>



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值