图论-最小生成树-prime算法&Kruskal算法 c++

本文介绍了图论中的最小生成树概念及其两种主要算法:Prim算法和Kruskal算法。这两种算法都利用了MST性质来找到图中的最小连通路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最小生成树解决的是找出图的最小连通路径,其具有MST性质:假设图G=(V,E)为一个无向连通图,U是顶点集V的一个非空子集,而u∈U,v∈V-U。若(u,v)为一条两个集合间具有最小权值的边,则必存在一颗包含(u,v)的最小生成树。Prime算法和Kruskal算法皆利用此性质得到最小生成树。

/*Prime算法
初始化:G=(V,E),U={v0},TE={ };
重复下列操作直到U=V
1.在E中寻找最短边(u,v),满足u∈U,v∈V-U;
2.U=U+{v};
3.TE=TE+{(u,v)};*/
int groph[MAX][MAX];
struct se
{
	int lowcost;
	int adjvex;
};

int minedge(vector<se>& shortedge, int n)//在shortedge中查找最小权值
{
	int t = INF, k = 0; 
	int i = 0;
	for (vector<se>::iterator it = shortedge.begin(); it != shortedge.end(); ++it,++i)
	{
		if (it->lowcost > 0 && it->lowcost < t)
		{
			t = it->lowcost;
			k = i;
		}
	}
	return k;
}

int prime(int n)
{
	int sum = 0;
	vector<se> shortedge;//存储已连接点集和未连接点集之间最短点集
	for (int i = 0; i < n; ++i)//初始化shortedge
	{
		se t;
		t.adjvex = 0;
		t.lowcost = groph[0][i];
		shortedge.push_back(t);
	}
	for (int i = 1; i < n; ++i)
	{
		int k = minedge(shortedge,n);//寻找最短边的邻接点
		cout << "(" << k << "," << shortedge[k].adjvex << ")" << shortedge[k].lowcost << endl;
		sum += shortedge[k].lowcost;
		shortedge[k].lowcost = 0;
		/*更新最短边集*/
		for (int j = 1; j < n; ++j)
		{
			if (groph[k][j] < shortedge[j].lowcost)
			{
				shortedge[j].adjvex = k;
				shortedge[j].lowcost = groph[k][j];
			}
		}
	}
	return sum;

}


/*Kruskal算法:G的最小生成树T,按权值从小到大依次考察边集E中边的顶点是否在一个连通分量里。
若在两个不同的连通分量里就将此边加入TE,并将两个连通分量连为一个,直到T中只有一个连通分量
初始化:G=(V,E),T=(U,TE),U=V,TE={ };
重复下列操作直到T中连通分量个数为1
1.找E中最短边(u,v);
2.若u,v位于两个不同的连通分量:
	将边(u,v)并入TE;
	将这两个连通分量合并;
3.在E中标记(u,v)不参与后续最短边选取*/
int groph[MAX][MAX];
struct et
{
	int from, to;
	int length;
};
list<et>  Egroph;

int findroot(int parent[],int v)//查询该点父节点用于检查是否在一个连通分量上
{
	int t = v;
	while (parent[t] > -1)
		t=parent[t];
	return t;
}

int kruskal(int n)
{
	int *parent=new int[n];
	int sum = 0,num=0;
	for (int i = 0; i < n; ++i)
	{
		parent[i] = -1;
	}
	for ( list<et>::iterator i = Egroph.begin(); i !=Egroph.end(); ++i)
	{
		//判断两个顶点是否位于相同的连通分量
		int vex1 = findroot(parent, i->from);
		int vex2 = findroot(parent, i->to);
		if (vex1 != vex2)
		{
			cout << "(" << i->from << "," << i->to << ")" << endl;
			sum += i->length;
			parent[vex2] = vex1;
			num++;
			if (num == n - 1)
				return sum;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值