数据结构——图的最小生成树

一、最小生成树的概念

图分为无向图和有向图,其中包括无权,有权(正权负权)图。

 定义:无向带权图G顶点个数为 m ,由G中 m 个点和 m - 1 条边构成的连通子图称为G的一条支撑树,也叫生成树。 边权之和最小的支撑树叫做最小支撑树(MST)。

最小支撑树无回路 

二、算法分析

 1.Prim算法(逐点加入)

Prim算法更适用于稠密图(点少边多)。

过程图解

数据结构——图的最小生成树_第1张图片

数据结构——图的最小生成树_第2张图片

数据结构——图的最小生成树_第3张图片

 

2.Kruskal算法(逐边加入)

利用并查集实现,将每个连通分量看作一个集合,顶点看作集合元素,每次查询一条权值最小的边,查询该边的两端是否在同一个集合内,若不在就将这两个集合合并,将该边加入支撑树中。Kruskal算法更适用于稀疏图(点多边少)。

 过程图解

数据结构——图的最小生成树_第4张图片

 

数据结构——图的最小生成树_第5张图片

数据结构——图的最小生成树_第6张图片

三、求最小支撑树例题——Prim

1. 题目说明

数据结构——图的最小生成树_第7张图片

 2. 代码实现


#include
using namespace std;
#define WQ 65535//有符号的最大值表示无穷大

int edge[2000][2000];//邻接矩阵
long long sum;//权值之和
int TE[1000];
int lowcost[2000];//最小权值数组 
int U[2000];
bool flag = false;
//构建邻接矩阵
void CreatGraph(int n, int e) {

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			edge[i][j] = WQ;
		}
	}
	for (int k = 0; k < e; k++) {
		int a, b, c;
		cin >> a >> b >> c;
		edge[a][b] = c;
		edge[b][a] = edge[a][b];
	}
}
void Prim(int n, int e) {
	flag = false;
	for (int i = 1; i <= n; i++) {
		lowcost[i] = edge[1][i];
		U[i] = 1;
	}
	U[1] = -1;
	int k = 1;
	for (int i = 1; i <= n - 1; i++) {
		int v = 0;
		int min = WQ;//无穷大
		for (int j = 1; j <= n; j++) {
			if (U[j] != -1 && lowcost[j] < min) {//初始化
				v = j;
				min = lowcost[j];
			}
		}
		if (v == 0) {
			flag = true;
			printf("There is no minimum spanning tree.\n");
			return;
			//图不连通
		}
		TE[k] = lowcost[v];
		k = k + 1;
		lowcost[v] = 0;
		U[v] = -1;
		for (int j = 1; j <= n; j++) {
			if (U[j] != -1 && edge[v][j] < lowcost[j]) {//更新权值
				lowcost[j] = edge[v][j];
				U[j] = v;
			}
		}
	}

	//return 0;
}

//主函数
int main() {
	int n;//顶点数
	int e;//边数
	while (scanf("%d%d", &n, &e) != EOF)
	{
		CreatGraph(n, e);//构建邻接矩阵
		Prim(n, e);
		if (flag == false) {
			for (int i = 1; i <= e; i++) {
				sum += TE[i];
			}
			cout << sum << endl;
		}
	}
	return 0;
}

你可能感兴趣的:(数据结构,算法)