• 还是畅通工程(最小生成树)


    题目:

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

    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
    Huge input, scanf is recommended.

    Hint

    Hint
    
    分析:
    很明显的最小生成树问题吧!
    用Prim算法和Kruscal算法都能解决的!!!

    下面是两种算法AC代码:
    Prim算法:
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    const int N=105;
    const int MAX=100000;
    int n;
    int dis[N][N];
    int lowcost[5000];
    void init()
    {
        for (int i=0;i<n+10;i++)
            for (int j=0;j<n+10;j++)
        {
            if (i==j)
                dis[i][j]=0;
            else
                dis[i][j]=MAX;
        }
    }
    void prim()
    {
        int k,mini,sum=0;
        for (int i=1;i<=n;i++)
            lowcost[i]=dis[1][i];
            for (int i=2;i<=n;i++)
            {
                mini=MAX;
                k=0;
                for (int j=1;j<=n;j++)
                {
                    if (lowcost[j]!=0&&lowcost[j]<mini)
                    {
                        mini=lowcost[j];
                        k=j;
                    }
                }
                sum+=lowcost[k];
                lowcost[k]=0;
                for (int j=1;j<=n;j++)
                {
                    if (lowcost[j]!=0&&lowcost[j]>dis[k][j])
                    {
                        lowcost[j]=dis[k][j];
                    }
                }
            }
        cout << sum << endl;
    }
    int main()
    {
        int a,b,c;
        while (cin>>n&&n!=0)
        {
            init();
            for (int i=1;i<=n*(n-1)/2;i++)
            {
                cin>>a>>b>>c;
                dis[a][b]=dis[b][a]=c;
            }
            prim();
        }
        return 0;
    }

    Kruskal算法:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n;
    int parent[5000];
    struct knot
    {
        int start;
        int ending;
        int cost;
    }a[5000];
    bool cmp(knot m,knot n)
    {
        return m.cost<n.cost;
    }
    int Find(int x)
    {
        while (parent[x]>0)
            x=parent[x];
        return x;
    }
    void kruskal()
    {
        int sum=0,k,l;
        for (int i=1;i<=n*(n-1)/2;i++)
            parent[i]=0;
        for (int i=1;i<=n*(n-1)/2;i++)
        {
            k=Find(a[i].start);
            l=Find(a[i].ending);
            if (k!=l)
            {
                parent[k]=l;
                sum+=a[i].cost;
            }
        }
        cout << sum << endl;
    }
    int main()
    {
        while (cin>>n&&n!=0)
        {
            memset(parent,0,sizeof(parent));
            for (int i=1;i<=n*(n-1)/2;i++)
                cin>>a[i].start>>a[i].ending>>a[i].cost;
            sort(a+1,a+1+n*(n-1)/2,cmp);
           kruskal();
        }
        return 0;
    }

     

  • 相关阅读:
    Python字符串的定义与常用操作
    Python中yield返回生成器的详细方法
    python中把列表中的字符串转成整型的3种方法
    python基础教程:修改Python列表中元素的几种方法
    极致性能设计——开篇
    MySQL设计与实现
    Java平台标准版工具参考
    为什么for循环中的a=a++,a总是0
    JVM 分析工具快速查询手册
    从现代计算机低层看待性能和并发
  • 原文地址:https://www.cnblogs.com/lisijie/p/7299494.html
Copyright © 2020-2023  润新知