zoukankan      html  css  js  c++  java
  • 月球美容计划之最小生成树(MST)

    寒假学的两个算法,普里姆,克鲁斯卡尔最终弄明确了。能够发总结了

    先说说普里姆,它的本质就是贪心。先从随意一个点開始,找到最短边,然后不断更新更新len数组,然后再选取最短边并标记经过的点,直到全部的点被标记。或者说已经选好了n-1条边。

    拿SDUTOJ2144为例。代码例如以下,可做模板

    #include <stdio.h>
    #include <string.h>
    #define INF 1000000
    
    //最小生成树
    //普里姆
    
    int G[200][200];
    int len[200];
    bool vis[200];
    
    int prm (int n)
    {
        int i,k,ans = 0;
        memset (vis,0,sizeof(vis));
    
        for (i = 2;i <= n;i++)//初始化
            len[i] = G[1][i];
        vis[1] = 1;
        for (i = 1;i < n;i++) //循环n - 1次
        {                     //由于n个顶点的MST一定是n-1条边
            int imin = INF,xb;
            for (k = 1;k <= n;k++)
                if (!vis[k] && imin > len[k])
                {
                    imin = len[k];
                    xb = k;
                }
    
            if (imin == INF)  //没有找到最小值,说明图不连通
                return -1;
    
            vis[xb] = 1;
            ans += imin;
    
            for (k = 1;k <= n;k++)
                if (!vis[k] && len[k] > G[xb][k])
                    len[k] = G[xb][k];
        }
    
        return ans;
    }
    
    int main()
    {
        int n,m;
    
        while (~scanf ("%d%d",&n,&m))
        {
            int i,k;
    
            for (i = 1;i <= n;i++)
                for (k = 1;k <= n;k++)
                    if (i != k)
                        G[i][k] = INF;
                    else
                        G[i][k] = 0;
    
            for (i = 0;i < m;i++)
            {
                int a,b,c;
                scanf ("%d%d%d",&a,&b,&c);
                if (G[a][b] > c)       //假设有边多次录入。选权最小的那个
                    G[a][b] = G[b][a] = c;
            }
    
            int ans = prm(n);
    
            printf ("%d
    ",ans);
        }
        return 0;
    }
    

    克鲁斯卡尔,一个排序一个并查集仅仅是表面。实质还是贪心,仅仅只是普里斯是任选一个点选最短路,而克鲁斯卡尔是看全局,全体边排序,当然,由于排序,导致时间复杂度不easy降下来。


    相同的题,代码例如以下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define INF 1000000
    
    //最小生成树
    //克鲁斯卡尔
    
    int vis[200];
    struct eg
    {
        int v,u,w;
    }e[100000];
    
    int cmp (const void *a,const void *b)
    {
        struct eg *ta = (struct eg *)a;
        struct eg *tb = (struct eg *)b;
    
        return ta->w - tb->w;
    }
    
    int fin (int a)
    {
        int r = a;
    
        while (vis[r] != r)
            r = vis[r];
        int k;
        while (vis[a] != a)
        {
            k = vis[a];
            vis[a] = r;
            a = vis[k];
        }
        return r;
    }
    
    int add (int a,int b)
    {
        vis[fin(a)] = fin (b);
        return 0;
    }
    
    int kls(int n,int m)
    {
        int i;
        int ans = 0;
    
        for (i = 0;i <=n;i++)
            vis[i] = i;
    
        for (i = 0;i < m;i++)
        {
            if (fin(e[i].u) != fin(e[i].v))
            {
                add (e[i].u,e[i].v);
                ans += e[i].w;
            }
        }
    
        return ans;
    }
    
    int main()
    {
        int n,m;
    
        while (~scanf ("%d%d",&n,&m))
        {
            int i,k;
            for (i = 0;i < m;i++)
            {
                int a,b,c;
                scanf ("%d%d%d",&a,&b,&c);
    
                e[i].u = a;
                e[i].v = b;
                e[i].w = c;
            }
            qsort(e,m,sizeof(e[0]),cmp);
            int ans = kls(n,m);
    
            printf ("%d
    ",ans);
        }
        return 0;
    }
    



  • 相关阅读:
    ubuntu下安装maven
    159.Longest Substring with At Most Two Distinct Characters
    156.Binary Tree Upside Down
    155.Min Stack
    154.Find Minimum in Rotated Sorted Array II
    153.Find Minimum in Rotated Sorted Array
    152.Maximum Product Subarray
    151.Reverse Words in a String
    150.Evaluate Reverse Polish Notation
    149.Max Points on a Line
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10505106.html
Copyright © 2011-2022 走看看