最小生成树

最小生成树

最小生成树就是在一个图中寻找一个联通图,必须包含原图的所有节点,且这个图的所有边的权值和最小.
为什么是一个树呢?因为只要求联通,就一定没有环,没有环不就是树了嘛!

Kruskal算法

Kruskal算法的核心是加边和判环.一条一条把边加上,如果加上会形成环就不加,最后弄成一个连通图.

假设有n个节点,就需要加(n-1)条边.为什么呢?因为每加上一条边,就会多连接一个点.
因为是要求最小生成树,所以先将所有边权值从小到大排序,挨个加边,加完的值一定是最小的.
判环主要用并查集实现,若两个节点的祖先不同,则加边后不会形成环,反之会形成环.

P3366 【模板】最小生成树

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;
int n,m,p,sum,father[5005];
struct Edge
{
	int x,y,w;
}a[200005];
int getfather(int);
void merge(int,int);
bool cmp(const Edge &a,const Edge &b);

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++) father[i]=i;
	for(int i=1;i<=m;i++)
	{ 
		cin>>a[i].x>>a[i].y>>a[i].w;
	}
	sort(a+1,a+m+1,cmp);
	int k=0;
	for(int i=1;i<=m;i++)
	{
		if(getfather(a[i].x)!=getfather(a[i].y))
		{
			++k;
			merge(a[i].x,a[i].y);
			sum+=a[i].w;
		}
		if(k==n-1) break;
	}
	cout<<sum;
	
	return 0;
}

int getfather(int v)
{
	if(father[v]!=v) father[v]=getfather(father[v]);
	return father[v];
} 

void merge(int a,int b)
{
	father[getfather(a)]=getfather(b);
}

bool cmp(const Edge &a,const Edge &b)
{
	return a.w<b.w; 
}

Prim算法

核心:加点
(未完待续)

原文地址:https://www.cnblogs.com/huaruoji/p/12217305.html