• 最小生成树专题


    POJ1258

         Prim算法。

    View Code
    #include <cstdio>
    #include <cstring>
    #define MAXN 110
    
    int d[MAXN][MAXN];
    int edge[MAXN]; 
    bool visit[MAXN];
    int n;
    
    int Prim()
    {
        int i, j, k, mst = 0;
        memset(visit, false, sizeof(visit));
        memset(edge, 0x3f, sizeof(edge));
        edge[0] = 0;
        for(i = 0; i < n; i ++)
        {
            k = -1;
            for(j = 0; j < n; j ++)
                if(!visit[j] && (k == -1 || edge[j] < edge[k]))
                    k = j;
            visit[k] = true;
            mst += edge[k];
            for(j = 0; j < n; j ++)
            {
                if(!visit[j] && d[k][j] && d[k][j] < edge[j]) 
                    edge[j] = d[k][j];
            }
        }
        return mst;
    }
    
    int main()
    {
        while(~scanf("%d", &n))
        {
            for(int i = 0; i < n; i ++)
            {
                for(int j = 0; j < n; j ++)
                {
                    scanf("%d", &d[i][j]);
                }
            }
            printf("%d\n", Prim());;
        }
        return 0;
    }

         Kruskal算法。

    View Code
    #include <cstdio>
    #include <algorithm>
    #define MAXN 100100
    using namespace std;
    
    int u[MAXN], v[MAXN], w[MAXN], p[MAXN], r[MAXN];
    int n, m, id;
    
    int cmp(const int i, const int j)
    {
        return w[i] < w[j];
    }
    
    int find(int x)     //并查集,保证放入的边不构成环
    {
        return p[x] == x ? x : p[x] = find(p[x]);
    }
    
    int Kruskal()
    {
        int mst = 0;
        for(int i = 0; i < n; i ++) //初始化并查集的根节点为自己
            p[i] = i;
        for(int i = 0; i < m; i ++) // 边编号
            r[i] = i;
        sort(r, r + m, cmp);
        for(int i = 0; i < m; i ++)
        {
            int e = r[i];
            int x = find(u[e]);
            int y = find(v[e]);
            if(x != y)               // x == y表示新加入的边会构成环,所以即使当前的边是最小权值,也不能要
            {
                mst += w[e];
                p[x] = y;            // 将新加入的安全边的两个端点加入并查集,可以以任意一个点为根,所以写成p[y] = x也是可以的
            }
        }
        return mst;
    }
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
        while(~scanf("%d", &n))
        {
            id = 0;
            m = n * n;
            for(int i = 0; i < n; i ++)
            {
                for(int j = 0; j < n; j ++)
                {
                    u[id] = i, v[id] = j;
                    scanf("%d", &w[id ++]);
                }
            }
            printf("%d\n", Kruskal());
        }
        return 0;
    }

    POJ2485

    View Code
    /*
    Memory: 568K        Time: 172MS
    Language: C++    Result: Accepted
    
    */
    #include <cstdio>
    #include <cstring>
    #define MAXN 510
    int d[MAXN][MAXN];
    int min[MAXN];
    bool flag[MAXN];
    
    int n, m;
    
    int Prim()
    {
        int max = 0;
        int i, j, k;
        memset(min, 0x3f, sizeof(min));
        memset(flag, false, sizeof(flag));
        min[0] = 0;
        for(i = 0; i < n; i ++)
        {
            k = -1;
            for(j = 0; j < n; j ++)
            {
                if(!flag[j] && (k == -1 || min[j] < min[k]))
                    k = j;
            }
            flag[k] = true;
            if(min[k] > max)
            {
                max = min[k];
            }
            for(j = 0; j < n; j ++)
            {
                if(!flag[j] && d[k][j] && d[k][j] < min[j])
                    min[j] = d[k][j];
            }
        }
        return max;
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            scanf("%d", &n);
            for(int i = 0; i < n; i ++)
            {
                for(int j = 0; j < n; j ++)
                {
                    scanf("%d", &d[i][j]);
                }
            }
            printf("%d\n", Prim());
        }
        return 0;
    }
    View Code
    /*
    Memory: 820K        Time: 297MS
    Language: C++    Result: Accepted
    */
    #include <cstdio>
    #include <algorithm>
    #define MAXN 250010
    using namespace std;
    int w[MAXN], r[MAXN], p[MAXN], u[MAXN], v[MAXN];
    int n, m;
    
    int find(int x)
    {
        return p[x] == x ? p[x] : p[x] = find(p[x]);
    }
    
    bool cmp(int i, int j)
    {
        return w[i] < w[j];
    }
    
    int Kruskal()
    {
        int i, max = 0;
        m = n * n;
        for(i = 0; i < n; i ++)
            p[i] = i;
        for(i = 0; i < m; i ++)
            r[i] = i;
        sort(r, r + m, cmp);
        for(i = 0; i < m; i ++)
        {
            int e = r[i];
            int x = find(u[e]);
            int y = find(v[e]);
            if(x != y)
            {
                if(w[e] > max) max = w[e];
                p[x] = y;
            }
        }
        return max;
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            int id = 0;
            scanf("%d", &n);
            for(int i = 0; i < n; i ++)
            {
                for(int j = 0; j < n; j ++)
                {
                    u[id] = i, v[id] = j;
                    scanf("%d", &w[id ++]);
                }
            }
            printf("%d\n", Kruskal());
        }
        return 0;
    }

        努力更新中……
       

  • 相关阅读:
    添加组合索引时,做相等运算字段应该放在最前面
    常用位运算
    redis php扩展简单使用
    mysql优化之简单概念
    mysql优化之sql语句优化
    简单画图 gd库函数
    win下 安装mongodb
    伪静态之实际应用
    tomcat win简单配置
    docker
  • 原文地址:https://www.cnblogs.com/huangfeihome/p/2667474.html
Copyright © 2020-2023  润新知