最小生成树算法
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;
}