Loading

最小生成树算法

1最小生成树算法

1.1算法kruskal

思想:每次在边集e中选出一条权值最小的边,如果两边的点不在一个集合中,则合并两个集合。合并集合用并查集来实现。

代码:

struct DSU{
	ll fa[N];
	
	inline void init(ll n){
		for(ll i=1;i<=n;i++) fa[i]=i;
	}
	
	inline ll find(ll x){
		return x==fa[x]?x:fa[x]=find(fa[x]);
	}
	
	inline bool merge(ll x,ll y){
		ll fax=find(x),fay=find(y);
		if(fax==fay) return 0;
		fa[fax]=fay;
		return 1;
	}
};

inline ll kruskal(){
	ll sum=0;
	sort(e.ed+1,e.ed+1+m);
	for(ll i=1;i<=m;i++)
		if(dsu.merge(e.ed[i].from,e.ed[i].to)) in_mst[e.ed[i].next]=1,in_mst[e.ed[i].next-1]=1,sum+=e.ed[i].w;
	return sum;
}

1.2算法prim

思想:每次从不是最小生成树的节点中选一个距离最小生成树节点最近的,加入到最小生成树中,可以用堆来优化,稠密图prim比kruskal更优。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ld long double
#define ll long long
#define ull unsigned long long
#define N 50100
#define M 500100
using namespace std;

const int INF=0x3f3f3f3f;

inline ll read(){
	ll 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;
}

struct edge{
	int to,next,w;
	inline void intt(int to_,int ne_,int w_){
		to=to_;next=ne_;w=w_;
	}
};
edge li[M];
int head[N],tail;

inline void add(int from,int to,int w){
	li[++tail].intt(to,head[from],w);
	head[from]=tail;
}

bool vis[N];
struct rode{
	int id,dist;
	rode() {}
	rode(int id,int dist) : id(id),dist(dist) {}
	inline bool operator < (const rode b) const {
		return dist>b.dist;
	}
};

priority_queue<rode> q;

int n,m,ans,mind[N];

inline int prim(){
	memset(mind,INF,sizeof(mind));
	int sum=0;q.push(rode(1,0));
	while(q.size()){
		rode top=q.top();q.pop();
		if(vis[top.id]) continue;
		vis[top.id]=1;sum+=top.dist;mind[top.id]=top.dist;
//		printf("%d %d\n",top.id,top.dist);
		for(int x=head[top.id];x;x=li[x].next){
			int to=li[x].to;
			if(vis[to]||li[x].w>=mind[to]) continue;
			q.push(rode(to,li[x].w));
		}
	}
	return sum;
}

int main(){
	n=read();m=read();
	for(int i=1;i<=m;i++){
		int from=read(),to=read(),w=read();
		add(from,to,w);add(to,from,w);
	}
	ans=prim();
	printf("%d",ans);
	return 0;
}
posted @ 2021-03-30 17:12  hyl天梦  阅读(79)  评论(0编辑  收藏  举报