• 算法实验11:还是畅通工程(最小生成树 kruscal prim)


    算法实验11:还是畅通工程

    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
    • kruscal

    给边从小到大排序,判断该条边的两端点是否属于同一个祖先(同一个连通子集),是的话跳过,否则选上

    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    struct Node {
        int a,b,c;
    }edge[100005];
    bool cmp(Node p,Node q) {
        return p.c < q.c;
    }
    int fa[105];
    int find_(int a) {
        int x = a;
        while(x!=fa[x]){
            x = fa[x];
        }
        fa[a] = x;
        return x;
    }
    void union_(int x,int y) {
        int fx = find_(x);
        int fy = find_(y);
        if(fx != fy) {
            fa[fy] = fx;
        }
    }
    
    int main()
    {
        int n,m;
        while(cin >> n&&n) {
            m = n*(n-1)/2;
            for(int i = 0; i < m; i++) {
               cin >> edge[i].a >> edge[i].b >> edge[i].c;
            }
            sort(edge,edge+m,cmp);
            for(int i = 1; i <= n; i++) fa[i] = i;
            int ans = 0,sum = 0;
            for(int i = 0; i < m; i++) {
                if(sum == n-1) break;
                if(find_(edge[i].a) != find_(edge[i].b)) {
                    sum++;
                    ans += edge[i].c;
                    union_(edge[i].a,edge[i].b);
                }
            }
            cout << ans << endl;
        }
        return 0;
    }
    • prim

    设两个数组a[i],b[i],a[i]表示起点为b[i],终点为i的边的权值 假设一开始的起点都为1

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int inf = 0x3f3f3f3f;
    
    int edge[105][105];
    int a[105],b[105];
    int main()
    {
        int n,m;
        while(cin >> n&&n) {
            m = n*(n-1)/2;
            memset(edge,inf,sizeof(inf));
            int u,v,w;
            for(int i = 0; i < m; i++) {
                cin >> u >>v >>w;
                edge[u][v] = w;
                edge[v][u] = w;
            }
            a[1] = 0,b[1] = 0;
            int ans = 0;
            for(int i = 2; i <= n; i++) a[i] = edge[1][i],b[i] = 1;
            for(int i = 2; i <= n; i++) {
                int maxn = inf,k;
                for(int j = 1; j <= n; j++) {
                    if(a[j] < maxn && a[j] != 0) {
                        maxn = a[j];
                        k = j;
                    }
                }
                ans += maxn;
                a[k] = 0,b[k] = 0;
                for(int j = 1; j <= n; j++) {
                    if(a[j] > edge[k][j]) {
                        b[j] = k;
                        a[j] = edge[k][j];
                    }
                }
            }
            cout << ans << endl;
        }
        return 0;
    }
  • 相关阅读:
    Intellij idea安装
    c# .net 我的Application_Error 全局异常抓取处理
    c# .net Global.asax文件的作用
    ASP.NET机制详细的管道事件流程(转)
    正则表达式_学习笔记
    c# .net获取随机字符串!
    c# 动态调用WCF方法笔记!
    Web Service和WCF的区别。其实二者不属于一个范畴!!!
    c# .net获取文件夹下的所有文件(多层递归),并获取区间数据(Jsion,xml等数据)写出到处理文件,学习分享~
    c#.net单例模式的学习记录!
  • 原文地址:https://www.cnblogs.com/LLLAIH/p/11764240.html
Copyright © 2020-2023  润新知