最小生成树 模板

首先明确树的定义:在无向图中,联通且不含圈的图称为树。

最小生成树一般解决类似村边很多路,修一条能连通所有村且路的费用最少(权值最小);

下面介绍prim算法和kruskal算法:

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

prim算法:类似迪杰斯特拉算法,都是从某个顶点出发,不断添加边的过程。Prim的思想是将任意节点作为根,再找出与之相邻的所有边(用一遍循环即可),再将新节点更新并以此节点作为根继续搜,维护一个数组:dis,作用为已用点到未用点的最短距离。

模板题:https://www.luogu.org/problemnew/show/P3366

测试数据:4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

输出:7

prim算法+堆优化:O(NlogN)

#include
using namespace std;
const int N=5005,M=4e5+7;
int vis[N],dis[N];
int head[M],ver[M],nex[M],edge[M];
int cnt,n,m,ans;
void add(int a,int b,int w){
	ver[++cnt] = b;
	edge[cnt] = w;
	nex[cnt] = head[a];
	head[a] = cnt;
}
void init(){
	memset(head,-1,sizeof head);
	memset(dis,0x3f,sizeof dis);
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++){
		int a,b,w;
		scanf("%d %d %d",&a,&b,&w);
		add(a,b,w);
		add(b,a,w);
	}
}
priority_queue > q;
void prim(){
	dis[1]=0;
	cnt=0;
	q.push(make_pair(0,1));
	while(!q.empty() && cnt dis[j]) minn = dis[j],k=j;
		vis[k] = 1;
		ans += dis[k];
		for(int j=1;j<=n;j++)
		if(!vis[j] && dis[j] > w[k][j]) dis[j] = w[k][j];
	}
	printf("%d",ans);
}*/
int main(){
	init();
	prim();
	if(cnt==n)
	printf("%d",ans);
	else
	printf("orz");
	return 0;
}

第二种:kruskal算法,先对边排序,每次在不成环(并查集)的前提下加入最小边;

#include
using namespace std;
struct EG{
	int from,to,w;
	bool operator < (const EG &b)const{
		return w

 

你可能感兴趣的:(图论,模板)