最小生成树

最小生成树

最小生成树有两种算法primkruskal算法,前一种算法适用于稠密图,后一种适用于稀疏图。

1. prim

prim算法的思路是先找一个还没加入最小生成树集合的最近的点,然后用他去更新其他点距离最小生成树集合的距离,公式为

$$
dis[i]=min(dis[i],edge[t][i])
$$

更新完之后再把这个点加入到集合之中

代码如下

#include<bits/stdc++.h>
using namespace std;
const int N=5100;
#define inf 0x7fffffff
int n,m,edge[N][N],dis[N];
bool vis[N];
int prim(){
int res=0,cnt=0;//cnt记录有几个点加入到最小生成树之中
for(int i=1;i<=n;i++) dis[i]=inf;
for(int i=0;i<n;i++){
int t=-1;
for(int j=1;j<=n;j++){
if(!vis[j]&&(t==-1||dis[t]>dis[j])) t=j;
}
if(i&&dis[t]==inf){
return -1;
}
if(i) res+=dis[t],cnt++;
for(int j=1;j<=n;j++){
dis[j]=min(dis[j],edge[t][j]);
}
vis[t]=1;
}
if(cnt==n-1) return res;
else return -1;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
edge[i][j]=edge[j][i]=inf;
}
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
edge[u][v]=edge[v][u]=min(edge[u][v],w);
}
int t=prim();
if(t==-1) cout<<"orz";//就是没找到、
else cout<<t;
return 0;
}

第二种算法是kruskal他是把集合用用一个并查集保存起来,同时将边进行了从小到大的排序,这也导致他的时间复杂度达到l0(logn)

他到算法步骤是先将边从小到大进行排序,然后遍历所有边,最后如果边数达到了n-1的话就形成了最小生成树

代码如下

#include<bits/stdc++.h>
using namespace std;
const int N=2*1e5+100;
struct Edge{
int from,to,dis;
bool operator<(const Edge&x)const{
return dis<x.dis;
}
}edge[N];
int n,m,cnt,fa[5100];
int find(int x){
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
void kruskal(){
for(int i=1;i<=n;i++) fa[i]=i;
sort(edge+1,edge+1+m);
int res=0,cnt=0;//记录边数
for(int i=1;i<=m;i++){
int a=edge[i].from,b=edge[i].to,c=edge[i].dis;
a=find(a),b=find(b);
if(a!=b){
res+=c;
cnt++;
fa[a]=b;
}
}
if(cnt<n-1) cout<<"orz";
else cout<<res;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
edge[++cnt].from=u;
edge[cnt].to=v;
edge[cnt].dis=w;
}
kruskal();
return 0;
}
 
posted @ 2022-06-13 10:36  silky__player  阅读(281)  评论(0编辑  收藏  举报