zoukankan      html  css  js  c++  java
  • HDU-1233-还是畅通工程(最小生成树kruscal)

    还是畅通工程

    Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 45838 Accepted Submission(s): 20885

    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

    #include<stdio.h>///kruscal算法
    #include<algorithm>
    using namespace std;
    struct Road///包括这条边是从哪儿(from)到(to)哪儿,以及长度(val)
    {
        int x,y,dis;
    } road[10000];
    bool cmp(Road a,Road b)///结构体排序
    {
        return a.dis<b.dis;///给长度按从小到大排序
    }
    int finds[150];
    int Find(int n)///并查集的查找函数
    {
        return finds[n]==n?n:Find(finds[n]);
    }
    void join(int x,int y)///合为一个集合中
    {
        finds[Find(x)]=Find(y);
    }
    int main()
    {
        int n,i,j;
        while(scanf("%d",&n)!=EOF)///n个城镇,m条边
        {
            if(!n)break;
            int m=n*(n-1)/2;///这里是边的数量
            for(i=0; i<m; i++)///输入从哪儿到哪儿,这里不是利用邻接矩阵了,直接给边赋予信息
            {
                scanf("%d%d%d",&road[i].x,&road[i].y,&road[i].dis);
            }
            sort(road,road+m,cmp);///给边按从小到大排序
            for(i=0; i<=n; i++)///预处理
            {
                finds[i]=i;
            }
            int sum=0,flag=0;
            for(i=0; i<m; i++)///从长度小的边开始遍历
            {
                if(Find(road[i].x)!=Find(road[i].y))///第一小的边的开始和结尾上司不同
                {///这里如果他们的上司不一样,说明他们之间没有连通,不会构成环状,可以选择这条边加上
                    flag++;///已经加入的边计数
                    join(road[i].x,road[i].y);///并把相应节点合为一个集合(表示已经连通)
                    sum+=road[i].dis;///总长度加上这条边
                }///再找下一个短边的两个城镇是否连通,没连通则将其连通,总和加上那条边的长度
                if(flag==m-1)break;///记住这里是边的数量,m的数量,不是n的数量
            }///因为n个城镇不会超过n-1条边,因此当达到这个边数目时就可以跳出了,此时总和就是所有最短边总和
            printf("%d
    ",sum);
        }
        return 0;
    }
    
  • 相关阅读:
    POJ 3468 A Simple Problem with Integers
    BZOJ 4430 Guessing Camels
    POJ 2309 BST
    POJ 1990 MooFest
    cf 822B Crossword solving
    cf B. Black Square
    cf 828 A. Restaurant Tables
    Codefroces 822C Hacker, pack your bags!
    [HDU 2255] 奔小康赚大钱
    [BZOJ 1735] Muddy Fields
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11794355.html
Copyright © 2011-2022 走看看