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;
    }
    



  • 相关阅读:
    231. Power of Two
    204. Count Primes
    205. Isomorphic Strings
    203. Remove Linked List Elements
    179. Largest Number
    922. Sort Array By Parity II
    350. Intersection of Two Arrays II
    242. Valid Anagram
    164. Maximum Gap
    147. Insertion Sort List
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6735094.html
Copyright © 2011-2022 走看看