Loading

最小生成树

Kruskal算法

加边法,初始边数为0,每次选择一条满足条件的最小代价边,加入到最小生成树的边集合里。 

适用于简单图

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
int n,m,tot=0,k=0;
int f[200010];
struct node {
    int from,to,dis;
}e[200010];

bool cmp(const node &a,const node &b) {
    return a.dis<b.dis;
}

int getf(int x) {
    return x==f[x]?x:f[x]=getf(f[x]);
}
void merge(int x,int y) {
    f[getf(y)]=getf(x);
}
int main( ) {
    cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>e[i].from>>e[i].to>>e[i].dis;
    for(int i=1;i<=n;i++) f[i]=i;
    sort(e+1,e+1+m,cmp);
    for(int i=1;i<=m;i++)  {
        if(k==n-1) break;
        if(getf(e[i].from)!=getf(e[i].to)) {
            merge(e[i].from,e[i].to);
            tot+=e[i].dis;
            k++;
        }
    }
    cout<<tot<<endl;
    return 0;
}
View Code

Prim算法

①选定一个点做为一个集合 a ,剩下的点为另一个集合 b

②将横跨两个集合且权重在其中最小的边加入最小生成树

③将刚刚加入最小生成树的边中不在集合 a 中的点加入集合 a,直到所有的点加入集合 a

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define maxn 102
#define inf 1000000
using namespace std;

int n,m;
int e[maxn][maxn];
int dis[maxn],vis[maxn];

void prim() {
    int k=1;
    vis[1]=1;
    for(int i=1;i<=n;i++) dis[i]=e[1][i];
    int pos;
    int sum=0;
    while(k<n) {
        int mini=inf;
        for(int i=1;i<=n;i++) {
            if(!vis[i]&&dis[i]<mini) {
                mini=dis[i];
                pos=i;
            }
        }
        vis[pos]=1; k++; sum+=dis[pos];

        for(int t=1;t<=n;t++) {
            if(!vis[t]&&dis[t]>e[pos][t]) dis[t]=e[pos][t];
        }
    }
    cout<<sum<<endl;
}

int main() {
    cin>>n>>m;
    memset(e,0,sizeof(e));
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
        if(i==j) e[i][j]=0;
        else e[i][j]=inf;

    int u,v,w;
    for(int i=0;i<m;i++) {
        cin>>u>>v>>w;
        e[u][v]=e[v][u]=w;
    }
    prim();

    return 0;
}
View Code

堆优化

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=5000+10;
const int M=200000+10;

int first[N],tot,vis[N],dis[N],n,m;
priority_queue <P,vector<P>,greater<P> >q;
struct edge {
    int v,w,net;
} e[M*2];

void add(int u,int v,int w) {
    e[tot].v=v; e[tot].w=w;
    e[tot].net=first[u];
    first[u]=tot++;
}
void prim() {
    int cnt=0,sum=0;
    dis[1]=0;
    q.push(make_pair(0,1));
    while(!q.empty()&&cnt<n) {
        int d=q.top().first,u=q.top().second;
        q.pop();
        if(!vis[u]) {
            cnt++;
            sum+=d;
            vis[u]=1;
            for(int i=first[u]; ~i; i=e[i].net)
                if(e[i].w<dis[e[i].v]) {
                    dis[e[i].v]=e[i].w;
                    q.push(make_pair(dis[e[i].v],e[i].v));
                }
        }
    }
    if(cnt==n) printf("%d\n",sum);
    else puts("orz");
}
int main( ) {
    int u,v,w;
    memset(first,-1,sizeof(first));
    memset(dis,0x3f3f3f3f,sizeof(dis));
    tot=0;
    cin>>n>>m;
    for(int i=1; i<=m; i++) {
        cin>>u>>v>>w;
        add(u,v,w);
        add(v,u,w);
    }
    prim();
    return 0;
}
View Code

 

posted @ 2019-09-21 12:28  qinuna  阅读(137)  评论(0编辑  收藏  举报