最小生成树算法

推一发博客!

最小生成树算法

1.prim算法

转载自 最小生成树

二者区别:Prim在稠密图中比Kruskal优,在稀疏图中比Kruskal劣。Prim是以更新过的节点的连边找最小值,Kruskal是直接将边排序。

二者其实都是运用贪心的思路

思路:prim算法是用链式前向星存图 传送门 ,通常是以编号为1的结点开始,更新dis数组,选中第二个点后再去更新dis数组,每次都将dis更新为最小值,直到边数为 顶点数-1(树的特性)。

如下是代码ios

inline int prim()
{
	for (int i = 2; i <= n; i++)
		dis[i] = inf;//初始化dis
	for (int i = head[1]; i > 0; i = edge[i].next)
	{
		dis[edge[i].v] = min(dis[edge[i].v], edge[i].w);//链式前向星遍历从1点出发的点并更新dis
	}
	while (++tot < n)
	{
		int maxx = inf;
		vis[now] = 1;
		for (int i = 1; i <= n; i++)
		{
			if (!vis[i] && maxx > dis[i])
			{
				maxx = dis[i];
					now = i;
			}
		}
		ans += maxx;
		for(int i=head[now];i>0;i=edge[i].next)
		dis[edge[i].v] = min(dis[edge[i].v], edge[i].w);//从now出发再次更新dis
	}
	return ans;
}

Kruskal算法

我的认为比prim算法好写

思路:把边按照权值从小到大排序,每次挑选权值最小的边,若加入该边会造成回路(经过并查集判断 传送门),直到边的总量比总点数少一。

如下代码web

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n, m, ans, eu, ev, cnt;
struct Edge 
{
	int u, v, w;
}e[200001];
inline int read()
{
	int x=0, f = 1; char ch = getchar();
	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar();}
	while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}//快读
void out(int k)
{
	if (k < 0) { putchar('-'); k = -k; }
	if (k > 9)out(k / 10);
	putchar(k % 10 + '0');
}//快写
int f[5001];
int find(int k)
{
	if (f[k] == k)return k;
	return f[k] = find(f[k]);
}
bool cmp(Edge a, Edge b)
{
	return a.w < b.w;
}//快排的依据
void gett()
{
	n = read(), m = read();
	for (int i = 1; i <= m; i++)
	{
		e[i].u = read(), e[i].v = read(), e[i].w = read();
	}
	for (int i = 1; i <= n; i++)
		f[i] = i;
}//初始化和读入
void kruskal() 
{
	sort(e, e + m, cmp);//按权值快排
	for (int i = 1; i <= m; i++)
	{
		eu = find(e[i].u), ev = find(e[i].v);
		if (eu == ev)continue;//若是祖宗相同说明造成了还就跳过
		ans += e[i].w;
		f[eu] = ev;
		if (++cnt == n - 1)//最小生成树已经构造好
			break;
	}
}
int main()
{
	gett();
	kruskal();
	out(ans);
}

完结撒花

整理不易,客官何不支持如下再走

在这里插入图片描述