Prime算法 与 Kruskal算法求最小生成树模板

算法原理参考链接 ==> UESTC算法讲堂——最小生成树

关于两种算法的复杂度分析 ==> http://blog.csdn.net/haskei/article/details/53132681

故稀疏图用 Kruskal、稠密图用 Prime、空间足够情况下都用 Prime + Heap 优化

下面的模板都是解决这一道题的模板

Prime模板

邻接矩阵版

#include<bits/stdc++.h>
using namespace std;
const int INF  = 0x3f3f3f3f;
const int maxn = 1e2 + 10;
int G[maxn][maxn], Dis[maxn], N;
bool vis[maxn];

int Prime(int st)
{
    int Cost = 0;
    for(int i=1; i<=N; i++)
        vis[i] = false,
        Dis[i] = G[st][i];
    vis[st] = true;

    for(int i=1; i<N; i++){
        int v, Min = INF;
        for(int j=1; j<=N; j++){
            if(!vis[j] && Dis[j]<Min){
                Min = Dis[j];
                v = j;
            }
        }

        Cost += Dis[v];
        vis[v] = 1;

        for(int j=1; j<=N; j++){
            if(!vis[j] && Dis[j] > G[v][j]){
                Dis[j] = G[v][j];
            }
        }
    }

    return Cost;
}

int main(void)
{
    while(~scanf("%d", &N)){

        for(int i=1; i<=N; i++)
            for(int j=1; j<=N; j++)
                scanf("%d", &G[i][j]);

        printf("%d
", Prime(1));
    }
    return 0;
}
View Code

邻接表 + 堆优化

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e2 + 10;
struct EDGE{ int v, nxt, w; };
struct NODE{ int v, cost;
    NODE(int vv, int cc):v(vv), cost(cc){};
    bool operator < (const NODE &rhs)const{
        return this->cost > rhs.cost;
    };
};

EDGE Edge[maxn*maxn];
bool vis[maxn];
int Head[maxn];
int N, cnt;

inline void init()
{
    for(int i=0; i<=N; i++)
        Head[i]=-1,vis[i]=false;
    cnt = 0;
}

inline void AddEdge(int from, int to, int weight)
{
    Edge[cnt].v = to;
    Edge[cnt].w = weight;
    Edge[cnt].nxt = Head[from];
    Head[from] = cnt++;
}

int Prime(int st)
{
    int Cost = 0;
    NODE tp(st, 0);
    priority_queue<NODE> que;
    que.push(tp);
    int EdgeCnt = 0;
    while(!que.empty() && EdgeCnt<cnt){
        tp = que.top(); que.pop();
        if(vis[tp.v]) continue;
        else vis[tp.v] = true;
        Cost += tp.cost;
        EdgeCnt++;
        for(int j=Head[tp.v]; j!=-1; j=Edge[j].nxt){
            if(!vis[Edge[j].v])
                que.push(NODE(Edge[j].v, Edge[j].w));
        }
    }
    return Cost;
}

int main(void)
{
    while(~scanf("%d", &N)){
        init();
        int Val;
        for(int i=1; i<=N; i++){
            for(int j=1; j<=N; j++){
                scanf("%d", &Val);
                if(Val){
                    AddEdge(i, j, Val);
                }
            }
        }
        printf("%d
", Prime(1));
    }
    return 0;
}
View Code

邻接表 + 配对堆优化

#include<bits/stdc++.h>
#include<ext/pb_ds/priority_queue.hpp>
using namespace __gnu_pbds;
using namespace std;
const int maxn = 1e2 + 10;
struct EDGE{ int v, nxt, w; };
typedef pair<int, int> pii;

EDGE Edge[maxn*maxn];
bool vis[maxn];
int Head[maxn];
int N, cnt;

inline void init()
{
    for(int i=0; i<=N; i++)
        Head[i]=-1,vis[i]=false;
    cnt = 0;
}

inline void AddEdge(int from, int to, int weight)
{
    Edge[cnt].v = to;
    Edge[cnt].w = weight;
    Edge[cnt].nxt = Head[from];
    Head[from] = cnt++;
}

int Prime(int st)
{
    int Cost = 0;
    __gnu_pbds::priority_queue< pii, greater<pii>, pairing_heap_tag > que;
    que.push(make_pair(0, st));
    int EdgeCnt = 0;
    while(!que.empty() && EdgeCnt<cnt){
        pii tp = que.top(); que.pop();
        int v = tp.second;
        if(vis[v]) continue;
        else vis[v] = true;
        Cost += tp.first;
        EdgeCnt++;
        for(int j=Head[v]; j!=-1; j=Edge[j].nxt){
            if(!vis[Edge[j].v])
                que.push(make_pair(Edge[j].w, Edge[j].v));
        }
    }
    return Cost;
}

int main(void)
{
    while(~scanf("%d", &N)){
        init();
        int Val;
        for(int i=1; i<=N; i++){
            for(int j=1; j<=N; j++){
                scanf("%d", &Val);
                if(Val){
                    AddEdge(i, j, Val);
                }
            }
        }
        printf("%d
", Prime(1));
    }
    return 0;
}
View Code

Kruskal模板

#include<bits/stdc++.h>
using namespace std;

const int maxn = 210;//最大点数
int c[maxn], N;//并查集使用
int cnt;

struct EDGE{
    int from, to, w;
    bool operator < (const EDGE &rhs) const{
        return this->w < rhs.w;
    };
}Edge[maxn*maxn];//储存边的信息,包括起点/终点/权值

inline void init()
{
    for(int i=0; i<=N; i++)
        c[i] = i;
    cnt = 0;
}

inline void AddEdge(int from, int to, int weight)
{
    Edge[cnt].from = from;
    Edge[cnt].to   = to;
    Edge[cnt].w    = weight;
    cnt++;
}

int Findset(int x)
{
    int root = x;
    while(c[root] != root)
        root = c[root];

    int idx;
    while(c[x] != root){ /// 路径压缩
        idx = c[x];
        c[x] = root;
        x = idx;
    }
    return root;
}

int Kruskal()//传入点数,返回最小生成树的权值,如果不连通返回-1
{
    sort(Edge,Edge+cnt);
    int EdgeCnt=0;//计算加入的边数
    int Cost=0;

    for(int i=0;i<cnt;i++){
        int R1 = Findset(Edge[i].from);
        int R2 = Findset(Edge[i].to);
        if(R1 != R2){
            Cost += Edge[i].w;
            c[R1]=R2;
            EdgeCnt++;
        }
        if(EdgeCnt==N-1) break;
    }
    if(EdgeCnt<N-1) return -1;//不连通
    else return Cost;
}

int main()
{
    while(~scanf("%d", &N)){
        init();
        int Val;
        for(int i=1; i<=N; i++){
            for(int j=1; j<=N; j++){
                scanf("%d", &Val);
                if(Val){
                    AddEdge(i, j, Val);
                }
            }
        }
        printf("%d
", Kruskal());
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/qwertiLH/p/7702364.html