最小生成树(MST)

基本概念:


在无向图中,连通且不含圈的图称为 “” 。  

给定无向图G=(V,E), 连接G中所有点,且边集是E的子集的树称为G的  “生成树” 。

在G的所有生成树中,权值最小的那颗树称为  “最小生成树” 。 


构造MST的算法有很多,最常见的有两个 : Kruskal算法   和   Prime算法  。


Kruskal算法:(适用于稀疏图

原理: 

1. 将图中所给出的所有边按照从小到大的顺序排列,然后依次考察每条边(u,v)。

2. 

情况1. u和v在同一个连通分量中,那么加入(u,v)后会形成环,因此不能选择。

情况2. u和v在不同的连通分量中,那么就加入(u,v)。


相关算法: 并查集

并查集: 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。


模板代码如下:

int u[MAX],v[MAX],w[MAX]; //u[i]表示一条边的起点,v[i]表示一条边的终点,w[i]表示改变的权值,i表示该边的编号。

int cmp(const int i,const int j)   //间接排序函数
{
    return w[i]



Prime算法: (适合稠密图

prime算法和边数无关,只和顶点数量有关。

基本原理:

1. 将一个图的顶点分为两部分,一部分是最小生成树中的结点(A集合),另一部分是未处理的结点(B集合)。

2. 首先选择一个顶点放入集合A中,然后遍历集合B中的所有顶点,找出与A中顶点关联的所有边中权值最小的一条边(顶点为v),将v从B集合中删除并加入A集合。

3.递归重复步骤2,直到B集合中的顶点为空,结束此过程。


模板代码如下:

#include
#include
#include
#include
#include
using namespace std;
#define INF 0xffffff
#define MAXN 110
int map[MAXN][MAXN], lowcost[MAXN];
bool visit[MAXN];
int nodenum, sum;

void prim()
{
	int temp, k;
	sum = 0;
	memset(visit, false, sizeof(visit)); //初始化visit
	visit[1] = true;
	for(int i = 1; i <= nodenum; ++i) //初始化lowcost[i]
		lowcost[i] = map[1][i];
	for(int i = 1; i < nodenum; ++i)//找生成树集合点集相连最小权值的边
	{
		temp = INF;
		for(int j = 1; j <= nodenum; ++j)
			if(!visit[j] && temp > lowcost[j])
				temp = lowcost[k = j];
		if(temp == INF) break;
		visit[k] = true;                  //加入最小生成树集合
		sum += temp;                      //记录权值之和
		for(int j = 1; j <= nodenum; ++j) //更新lowcost数组
			if(!visit[j] && lowcost[j] > map[k][j])
				lowcost[j] = map[k][j];
	}
}


你可能感兴趣的:(编程,最小生成树)