zoukankan      html  css  js  c++  java
  • hdoj1233-还是畅通工程(并查集-kruskal && prim)

    题目链接
    Problem Description
    某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。

    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( < 100 );随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离。为简单起见,村庄从1到N编号。
    当N为0时,输入结束,该用例不被处理。

    Output
    对每个测试用例,在1行里输出最小的公路总长度。

    Sample Input
    3
    1 2 1
    1 3 2
    2 3 4
    4
    1 2 1
    1 3 4
    1 4 1
    2 3 3
    2 4 2
    3 4 5
    0

    Sample Output
    3
    5

    思路:

    此题主要考察最小生成树,我用的是kruskal算法和并查集, 然后再用prim算法也写了一遍.
    代码其实很简单。

    并查集-kruskal:

    //Exe.Time  Exe.Memory
    //1060MS    1868K
    
    #include <iostream>
    #include <algorithm>
    #include <fstream>
    using namespace std;
    
    //边
    struct Edge
    {
        int v, u, w;
    };
    
    
    Edge e[5010];
    int n;
    int father[105];
    
    int cmp(Edge e1, Edge e2)
    {
        return e1.w <= e2.w;
    }
    
    //初始化并查集
    void init()
    {
        for(int i = 1; i <= n; ++ i)
        {
            father[i] = i;
        }
    }
    
    //寻找集合根节点,并按路径优化
    int find(int node)
    {
        int x = node;
        if(x != father[x])
        {
            father[x] = find(father[x]);
        }
        return father[x];
    }
    
    //将两个集合合并
    void unit(int x, int y)
    {
        int x0 = find(x);
        int y0 = find(y);
        father[y0] = x0;
    }
    
    //最短路算法
    int kruskal()
    {
        int total_weight = 0;
        init();
        int cnt = n * (n - 1) / 2;
        sort(e, e + cnt, cmp);//将边按权值大小排序
        int count = 0;
        for(int i = 0; i < cnt; ++ i)
        {
            //v所在集合为最小生成树顶点的集合,当两点不在一个集合时进行合并,并且将边加入最小生成树
            if(find(e[i].v) != find(e[i].u))
            {
                total_weight += e[i].w;
                unit(e[i].v, e[i].u);
                count ++;
                //cout << e[i].v << "--->" << e[i].u << " = " << e[i].w << endl;
            }
            //当边数达到n-1时,最小生成树构造完毕
            if(count == n - 1)
            {
                break;
            }
        }
        return total_weight;
    }
    
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
    
    //  ifstream cin("data.in");
    
        while(cin >> n && n != 0)
        {
    
            int cnt = n * (n -1) / 2;
            int total_weight = 0;
            for(int i = 0; i < cnt; ++ i)
            {
                cin >> e[i].v >> e[i].u >> e[i].w;
            }
            total_weight = kruskal();
            cout << total_weight << endl;
        }
        return 0;
    } 

    prim:

    //Exe.Time  Exe.Memory
    // 982MS      1848K 
    
    #include <iostream>
    #include <algorithm>
    #include <fstream>
    #include <cstring>
    #include <vector>
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    
    int n;
    int dist[105];
    int data[105][105];
    bool vis[105];
    
    int prime(int v)
    {
        int total_weight = 0;
        dist[v] = 0;
        for(int i = 1; i <= n; ++ i)
        {
            int min_dist = INF, min_vertex;
            for(int j = 1; j <= n; ++ j)
            {
                if(!vis[j] && dist[j] < min_dist)
                {
                    min_vertex = j;
                    min_dist = dist[j];
                }
            }
    
            vis[min_vertex] = true;
            total_weight += min_dist;
    
            for(int j = 1; j <= n; ++ j)
            {
                if(!vis[j] && dist[j] > data[j][min_vertex])
                {
                    dist[j] = data[j][min_vertex];
                }
            }   
        } 
        return total_weight;
    }
    
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
    
    //  ifstream cin("data.in");
    
        while(cin >> n && n != 0)
        {
            memset(data, INF, sizeof(data));
            memset(vis, false, sizeof(vis));
            memset(dist, INF, sizeof(dist));
            for(int i = 0; i < n; i ++)
            {
                //cout << vis[i] << "  " << dist[i] << endl;
            }
            int cnt = n * (n -1) / 2;
            int total_weight = 0;
            for(int i = 0; i < cnt; ++ i)
            {
                int x, y, w;
                cin >> x >> y >> w;
                data[x][y] = min(data[x][y], w);
                data[y][x] = min(data[y][x], w);
            }
            total_weight = prime(1);
            cout << total_weight << endl;
        }
        return 0;
    } 
  • 相关阅读:
    《软件测试经验与教训》—读书笔记
    【转】性能测试工程师的素质
    【转】如何成为优秀的性能测试工程师
    性能测试学习之路
    FTP 、TCP/IP、HTTP、Cookies、Session
    Loadrunner工具介绍
    tesseract-ocr图像识别技术(一)
    MongoDB 自动分片 auto sharding
    mongodb 3.0下载安装、配置及mongodb最新特性、基本命令教程详细介绍
    java使用memcached2--集群部署
  • 原文地址:https://www.cnblogs.com/topk/p/6580110.html
Copyright © 2011-2022 走看看