【图(下)】最小生成树问题

一、什么是最小生成树(Minimum Spanning Tree)

  • 是一棵
    • 无回路
    • |V|个顶点必定有|V|-1条边
  • 生成
    • 包含所有顶点
    • |V|-1条边都在图里
  • 边的权重和最小
    在这里插入图片描述
    最小生成树存在↔ 图连通

二、贪心算法

  • 什么是“贪”:每一步都要最好的
  • 什么是“好”:权重最小的边
  • 须要约束:
    • 只能用图里有的边
    • 只能正好用掉|V|-1条边
    • 不能有回路

三、Prim算法— 让一棵小树长大

在这里插入图片描述

void Prim()
{
	MST = { s };//s维护折树中全部的顶点
	while (1)
	{
	//dist值的含义为距离这棵树的距离,树节点dist为0;
	//和树相邻节点dist为边权重,不相邻节点dist为无穷大。
		V = 未收录顶点中dist最小者;
		if (这样的V不存在)
			break;
	将V收录进MST: dist[V] = 0;//dist设为0表示收入树中
		for (V 的每一个邻接点W)//收录一个顶点会对该定点相邻顶点dist有影响
			if (W未被收录)
				if (E(V, W) < dist[W])
				{
					dist[W] = E(V, W);
					parent[W] = V;
				}
	}
	if (MST中收的顶点不到 | V |)//图不连通
		Error(“生成树不存在”);
}

Prim算法中的dist[V]初始化:
dist[V] = E(s,V)或正无穷web

parent[s] = -1
时间复杂度:
T = O( |V|2 ) 稠密图合算算法

三、Kruskal算法— 将森林合并成树

图中每个顶点均可以当作一棵树,每次找权重最小的边,把它收进来。每次把边收进来,就把两棵树并成一棵树,最后把全部的节点并成一棵树。
在这里插入图片描述svg

void Kruskal(Graph G)
{
	MST = {};//生成树集合中收集的元素为边
	while (MST 中不到 |V| -1 条边&& E 中还有边) {
		从E中取一条权重最小的边E(v, w);/* 最小堆*/E(v, w)从E中删除;
		if (E(V, W)不在MST中构成回路)/* 并查集*/E(V, W) 加入MST;
		else
			完全无视E(V, W);//生成树不要该边,E中也不要
	}
	if (MST 中不到 |V| -1 条边)//图不连通
		Error(“生成树不存在”);
}
  1. 从E中取一个权重最小的边,将E中元素组织成一个最小堆,每次取出一条边复杂度为log(E)。spa

  2. 判断E(v,w)(表示从顶点V到顶点W的一条边)的加入会不会在最小生成树中构成回路:
    使用并查集,加边E(v,w)以前检查顶点V和W,若是两者属于不一样的树,不会构成回路,在同一棵树中则会构成回路。code

时间复杂度:
T = O( |E| log |E| )
对于稀疏图比较划算xml