zoukankan      html  css  js  c++  java
  • poj-1251-最小生成树


    title: poj-1251-最小生成树
    date: 2018-11-20 16:38:14
    tags:

    • acm
    • 刷题
      categories:
    • ACM-最小生成树

    概述

    前段时间数据结构的课上提到了了最小生成树,,暑假的集训虽然再学并查集的时候看过一些,,但是之后好久没再用过,,早就忘记了,,,今天抽时间看了看,,把最小生成树的两个主要算法 primkruskal了解了一下,,,做几道题,,把自己的模板弄出来

    分析

    这两个算法很简单,,,看几遍就可以去敲去了,,,

    放几个别人的博客,,防止以后忘记了能快速回想起来
    还有一个

    prim算法主要的思路是将最小生成树慢慢的变大,,,
    kruskal算法主要是利用并查集将多个树也就是森林慢慢的合并成最后的树

    模板代码

    做了一道模板题,,题意就是对给定的一个图,,去掉一些边,,求花费最小的方案,,,其实就是权值和最小的那一种,,

    prim方法:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <string.h>
    #include <algorithm>
    
    using namespace std;
    
    const int inf = 0x3f3f3f3f;
    const int maxn = 30;
    
    int mp[maxn][maxn];
    bool vis[maxn];
    int dis[maxn];
    int n , m;
    
    int prim()
    {
        int sum = 0;
        memset(vis , false , sizeof vis);
        vis[1] = true;
        for(int i = 1; i <= n; ++i)
            dis[i] = mp[1][i];
    
        for(int i = 1; i < n; ++i)
        {
            int m = inf;
            int p = -1;
            //从所有的为加入最小生成树集合的点集里找到一个边权最小的
            for(int j = 1; j <= n; ++j)
                if(!vis[j] && dis[j] < m)
                {
                    m = dis[j];
                    p = j;
                }
            if(m == inf)    return -1;
            sum += m;
            vis[p] = true;
            //更新加入这个点之后能够到达其他点的值
            for(int j = 1; j <= n; ++j)
                if(!vis[j] && dis[j] > mp[p][j])
                    dis[j] = mp[p][j];
        }
        return sum;
    }
    int main()
    {
        while(scanf("%d" , &n) && n)
        {
            char c1 , c2;
            int m1 , m2;
            memset(mp , inf , sizeof mp);
            for(int i = 1; i <= n; ++i)
                mp[i][i] = 0;
            for(int i = 1; i <= n - 1; ++i)
            {
                scanf(" %c%d" , &c1 , &m1);
                for(int j = 1; j <= m1; ++j)
                {
                    scanf(" %c%d" , &c2 , &m2);
                    mp[c1 - 'A' + 1][c2 - 'A' + 1] = m2;
                    mp[c2 - 'A' + 1][c1 - 'A' + 1] = m2;
                }
            }
            printf("%d
    " , prim());
        }
        return 0;
    }
    

    kruskal方法:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <string.h>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 200;
    const int inf = 0x3f3f3f3f;
    int father[maxn];
    int n , m;
    
    struct edge
    {
        int u , v , w;
        bool operator < (const edge &r) const
        {
            return w < r.w;
        }
    }edge[maxn];
    int tot;
    void addedge(int _u , int _v , int _w)
    {
        edge[tot].u = _u;
        edge[tot].v = _v;
        edge[tot++].w = _w;
    }
    int find(int x)
    {
        if(x == father[x])  return x;
        else return father[x] = find(father[x]);
    }
    int kruskal()
    {
        for(int i = 1; i <= n; ++i)
            father[i] = i;
        sort(edge , edge + tot);
        int cnt = 0;
        int sum = 0;
        for(int i = 0; i < tot; ++i)
        {
            int t1 = find(edge[i].u);
            int t2 = find(edge[i].v);
            //u , v如果不在一个森林中就合并
            if(t1 != t2)
            {
                sum += edge[i].w;
                father[t1] = t2;
                ++cnt;
            }
            if(cnt == n - 1) break;
        }
        if(cnt < n - 1) return -1;
        else            return sum;
    }
    int main()
    {
        while(scanf("%d" , &n) && n)
        {
            char c1 , c2;
            int m1 , m2;
            tot = 0;
            for(int i = 1; i < n; ++i)
            {
                scanf(" %c%d" , &c1 , &m1);
                for(int j = 1; j <= m1; ++j)
                {
                    scanf(" %c%d" , &c2 , &m2);
                    addedge(c1 - 'A' + 1 , c2 - 'A' + 1 , m2);
                    addedge(c2 - 'A' + 1 , c1 - 'A' + 1 , m2);
                }
            }
            printf("%d
    " , kruskal());
        }
    }
    
    

    (end)

  • 相关阅读:
    CF932E Team Work
    BZOJ 4480 [JSOI2013] 快乐的jyy
    CF285E Positions in Permutations
    P4312 [COCI 2009] OTOCI / 极地旅行社
    P3327 [SDOI2015]约数个数和
    P3649 [APIO2014]回文串
    P3181 [HAOI2016]找相同字符
    P3346 [ZJOI2015]诸神眷顾的幻想乡
    P4248 [AHOI2013]差异
    P4512 【模板】多项式除法
  • 原文地址:https://www.cnblogs.com/31415926535x/p/9989951.html
Copyright © 2011-2022 走看看