最小生成树算法(Kruskal 算法 和 Prim算法)

本文详细介绍了图论中的两种最小生成树算法——Kruskal算法和Prim算法。Kruskal算法的时间复杂度为O(MlogM),通过将边按权值排序,依次选择不形成环的边构建生成树;而Prim算法的时间复杂度为O(n*n),通过不断寻找与已选节点相连的最短边来构建生成树。文章提供了完整的算法实现代码。

Kruskal算法:

   时间复杂度O(MlogM).

算法总结:

        首先把给的边按照边的权值进行从小到大的排序,每次从剩余的边中选择权值较小且边的两个顶点不在同一个集合内的边(就是不会产生回路的边),加入到生成树中,直到加入了n-1条边为止。

完整代码:

#include<stdio.h>
struct edge
{
	int u;
	int v;
	int w;
}e[10];
int n,m;
int f[7]={0},sum=0,count=0;
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;
		}
	}
	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()
{
	int i;
	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;
	for(i=1;i<=m;i++)
	{
		if(merge(e[i].u,e[i].v))
		{
			count++;
			sum+=e[i].w;
		}
		if(count==n-1)
			break;
	}
	printf("%d\n",sum);
	return 0;
}

Prim算法:

 时间复杂度是O(n*n)

算法总结:

     首先任意选择一个顶点加入生成树,接下来要找出一条边添加到生成树,这需要枚举每一个树顶点到每一个非树顶点所有的边,然后找到最短边加入到生成树,照此方法,重复操作n-1次,直到所有顶点都加入生成树中。

完整代码:

#include<stdio.h>
#define inf 99999999
int main()
{
	int n,m,i,j,k,min,a,b,c;
	int map[10][10],dis[10],book[10]={0};
	int count=0,sum=0;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
		{
			if(i==j)
				map[i][j]=0;
			else
				map[i][j]=inf;
		}
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a,&b,&c);
		map[a][b]=c;
		map[b][a]=c;
	}
	for(i=1;i<=n;i++)
		dis[i]=map[1][i];
	book[1]=1;
	count++;
	while(count<n)
	{
		min=inf;
		for(i=1;i<=n;i++)
		{
			if(book[i]==0&&dis[i]<min)
			{
				min=dis[i];
				j=i;
			}
		}
		book[j]=1;
		count++;
		sum+=dis[j];
		for(k=1;k<=n;k++)
		{
			if(book[k]==0&&dis[k]>map[j][k])
				dis[k]=map[j][k];
		}
	}
	printf("%d\n",sum);
	return 0;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值