• 九度OJ 1017:还是畅通工程 (最小生成树)


    时间限制:1 秒

    内存限制:32 兆

    特殊判题:

    提交:4789

    解决:2382

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

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

    输出:

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

    样例输入:
    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
    样例输出:
    3
    5
    来源:
    2006年浙江大学计算机及软件工程研究生机试真题

    思路:

    典型的最小生成树问题。通常有两种方法,Prim算法和Kruskal算法
    两种方法分别更适合于稠密图和稀疏图,个人比较喜欢用后一种方法,通常在算法实现上需结合并查集。

    两种算法介绍可参考博客:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html


    代码:

    #include <stdio.h>
    #include <stdlib.h>
     
    #define N 100
    #define M (N*(N-1)/2)
     
    typedef struct node {
        int x;
        int y;
        int d;
    } ROAD;
         
    int n;
    int pre[N+1];
    int count[N+1];
    int num;
         
    void init()
    {
        for (int i=1; i<=n; i++)
        {
            pre[i] = i;
            count[i] = 1;
        }
        num = n;
    }
     
    int find(int i)
    {   
        while (i != pre[i])
            i = pre[i];
        return i;
    }       
             
    int combine(int i, int j)
    {           
        int a = find(i); 
        int b = find(j);
        if (a != b)
        {   
            if (count[a] > count[b])
            {   
                pre[b] = a;
                count[a] += count[b];
                count[b] = 0;
            }
            else
            {
                pre[a] = b;
                count[b] += count[a];
                count[a] = 0;
            }
            num --;
            return 1;
        }
        else
            return 0;
    }
     
    int cmp(const void *a, const void *b)
    {
        return (((ROAD *)a)->d > ((ROAD *)b)->d) ? 1 : -1;
    }
     
    int main(void)
    {
        int m, i;
        ROAD r[M];
        int sum;
     
        while (scanf("%d", &n) != EOF && n)
        {
            m = n*(n-1)/2;
            for(i=0; i<m; i++)
                scanf("%d%d%d", &r[i].x, &r[i].y, &r[i].d);
            qsort(r, m, sizeof(r[0]), cmp);
     
            init();
            sum = 0;
            for(i=0; i<m; i++)
            {
                if(combine(r[i].x, r[i].y))
                    sum += r[i].d;
                if (num == 1)
                    break;
            }   
             
            printf("%d
    ", sum);
        }   
                 
        return 0;
    }    
    /**************************************************************
        Problem: 1017
        User: liangrx06
        Language: C
        Result: Accepted
        Time:20 ms
        Memory:916 kb
    ****************************************************************/


    编程算法爱好者。
  • 相关阅读:
    [日常工作] cmd以及bash 直接使用当前目录的方法
    [安全] 公司局域网病毒处理
    SQLserver 使用网络驱动器恢复数据库
    MiniDP与HDMI的关系
    Win10删除微软拼音输入法的方法
    SQLSERVER case when 的学习
    [日常工作]偷懒创建一个存储过程进行模拟工作.
    oracle 18c centos7 设置开机自动启动Oracle
    kali linux升级
    [日常工作]Oracle新增数据文件的小知识点
  • 原文地址:https://www.cnblogs.com/liangrx06/p/5084014.html
Copyright © 2020-2023  润新知