zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    activemq 异步和同步接收
    简单的activemq的封装和使用
    activemq 一个不错的ppt
    activemq 的小实验
    activemq api的封装
    观察者设计模式例子
    【转载】自定义类加载器例子
    京东拍拍网 笔试 搞java的去考C++ 苦逼
    java中用equals比较两个内容相同的字符数组
    云端飘 String s=new String("abc")创建了几个对象?
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7702364.html
Copyright © 2011-2022 走看看