您的位置:首页 > 其它

算法整理:最小生成树(mst)-Prim+Kruskal

2017-07-23 16:48 453 查看

Kruskal

大概思想:用并查集储存两点是否连通,将边按权重排序,每次取出权重最小的边,如果该边两端的点未连通,将该边的权重加入ans。最后判断是否每个点都和1(任意点)连通,若连通说明存在最小生成树,权和为ans;否则不存在最小生成树。

时间复杂度:O(e loge)

接下来是我的代码,在luogu通过了测试。

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int fa[5005];

struct edge{
int w,l,r;
}e[200005];
bool cmp(edge a,edge b){
return a.w<b.w;
}
int find(int k){
if(fa[k]==k)return k;

fa[k]=find(fa[k]);

return fa[k];
}

void merge(int a,int b){
a=find(a);
b=find(b);
if(a!=b)fa[a]=b;
return ;
}

int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)fa[i]=i;

for(int i=1;i<=m;++i){
int z,x,y;
scanf("%d%d%d",&x,&y,&z);
e[i].w=z;
e[i].l=x;
e[i].r=y;
}

sort(e+1,e+1+m,cmp);
int ans=0;
for(int i=1;i<=m;++i){
if(find(e[i].l)!=find(e[i].r)){
merge(e[i].l,e[i].r);
ans+=e[i].w;
}
}

int xx=find(1);
for(int i=2;i<=n;++i)
if(xx!=find(i)){printf("orz");/*while(1);*/return 0;}

printf("%d",ans);
/*while(12);*/
return 0;

}


Prim

大概思想:用优先队列和pair储存<点,到达该点的边权>,用邻接表储存边。先将1入队,vis[1]=1,然后遍历1的接边,如果该边另一端的点没有访问过且该边权值小于当前能到达该点的最小边权,更新最小边权,将<点,该边权>入队。之后同。 与bfs类似。

时间复杂度:O(n2)

代码,同在luoguAC。

#include<cstdio>
#include<queue>
#include<utility>
#include<vector>
#include<cstring>
#include<functional>
using namespace std;
struct edge{
int w,next,to;
}e[400005];
int dis[5005];
bool vis[5005];
int head[5005];
int n,m;
typedef pair<int,int> p;
void add(int x,int y,int w,int k){
e[k].to=y;
e[k].w=w;
e[k].next=head[x];
head[x]=k;
return ;
}
void prim(int k){

int ans=0;
int num=0;
memset(dis,127,sizeof dis);
dis[k]=0;
priority_queue<p,vector<p>,greater <p> >que;
que.push(p(dis[k],k));

while(  !que.empty() )
{
p pp=que.top();
que.pop();
int u=pp.second;
if(vis[u])continue;

vis[u]=1;
ans+=dis[u];
num++;

for(int i=head[u];i;i=e[i].next){
if(!vis[e[i].to]&&dis[e[i].to]>e[i].w){
dis[e[i].to]=e[i].w;
que.push(p(dis[e[i].to],e[i].to));
}
}

}

if(num==n)printf("%d",ans);
else printf("orz");
return ;
}

int main(){

scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z,i);
add(y,x,z,i+m);
}
prim(1);
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: