图论:求最小生成树的算法

Prim算法

输入:加权无向图G=(V,E)
输出:G的最小生成树
算法思想
集合U,T,U放顶点,T放树边
选择有最小权的(u,v),且u ∈U,v∈V-U,,将u加入U,(u,v)加入T
重复这一过程直到U=V

void Prim(costtype C[n+1][n+1])
{
	costtype LOWCOST[n+1]; //U与U-V中各一个顶点连成的具有最小权值的边 
	int CLOSEST[n+1];//U-V中的顶点 i对应的有最小权值的边的  U  中的 顶点 的编号 
	int i,j,k;
	costtype min;
	//默认1顶点一开始就在U中 
	for (int i=2;i<=n;i++)
	{
		LOWCOST[i]=C[1][i];
		CLOSEST[i]=1;
	}
	
	for(int i=2;i<=n;i++)
	{//找LOWCOST[]中最小的一个并记录下顶点编号k 
		min=LOWCOST[i];
		k=i;
		
		for (j=2;j<=n;j++)
		{
			if (LOWCOST[j]<min)
			{
				min=LOWCOST[j];
				k=j;
			}
		}
		
		cout<<"("<<k<<","<<CLOSEST[k]<<")"<<endl;
		
		
		LOWCOST[k]=infinity;//恭喜k加入顶点集U
		//infinity取一个很大的值 
		//更新顶点集U到U-V各点的最小权值 
		for (j=2;j<=n;j++)
			if (C[k][j]<LOWCOST[j]&&LOWCOST[j]!=infinity)
			{
				LOWCOST[j]=C[k][j];
				CLOSEST[j]=k; 
			}
	 } 
 } 

复杂度:O(n2),适合顶点不多的图

Kruskal算法

输入:连通图G=(V,E)
输出:最小生成树
算法思想

  • 每个顶点自身为一个连通分量
  • 按照边的权不减原则,依次考察E中每条边
  • 若考察的边分属两个不同连通分量,则将这条边加入最小生成树T,合并两个分量。否则放弃这条边(避免生成环路)。
  • 当整个图的连通分量数目为1时生成了一棵最小生成树
void Kruskal(EdgeSet edges,int n,int e)
{
	int bnf,edf;
	MFSET parents;
	Sort(edges);//根据边不减原则排序 
	
	for (int i=1;i<=n;i++)
		Initial(i,parents);//初始化每个顶点所在的连通分量 
		
	for (int i=1;i<=e;i++)
	{
		bnf=Find(edges[i].begin,parents);
		edf=Find(edges[i].end,parents);
		//若这条边的两个顶点不在同一连通分量 
		if (bnf!=edf)
		{
			Union(bnf,edf,parents);//合并为同一连通分量 
			
			
			//输出 
			cout<<"("<<edges[i].begin<<",";
			cout<<edges[i].end<<","edges[i].cost<<")";
			cout<<endl;
		}
	}
 } 

复杂度:时间复杂度O(E*log2E),适合求边稀疏的最小生成树

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值