zoukankan      html  css  js  c++  java
  • HDU1863_畅通project【Prim】【并查集】

    畅通project


    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 17867    Accepted Submission(s): 7552

    Problem Description
    省政府“畅通project”的目标是使全省不论什么两个村庄间都能够实现公路交通(但不一定有直接的公路相连,仅仅要能间接通过公路可达就可以)。

    经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编敲代码,计算出全省畅通须要的最低成本。


     
    Input
    測试输入包括若干測试用例。

    每一个測试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 
    行相应村庄间道路的成本,每行给出一对正整数,各自是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。

    为简单起见,村庄从1到M编号。

    当N为0时,所有输入结束,相应的结果不要输出。


     
    Output
    对每一个測试用例。在1行里输出全省畅通须要的最低成本。

    若统计数据不足以保证畅通,则输出“?”。

    Sample Input
    3 3
    1 2 1
    1 3 2
    2 3 4
    1 3
    2 3 2
    0 100
     
    Sample Output
    3
    ?

    Source

    浙大计算机研究生复试上机考试-2007年

    题目大意:给你M个村庄、N条路,即N条路所连接的两个村庄即路程。

    问是否能各个村庄都能有路达到,若不通。则输出'?',若通,则计算出连接

    全部村庄最小的路程和

    思路:先用并查集推断是否能全部村庄。

    把有路连接的村庄并到一个集合里。

    最后,若仅仅有一个集合。则全部村庄都能连接。若有两个以上,则肯定有

    村庄不能到达。

    然后用Prim算法计算出图的最小生成树。

    #include<stdio.h>
    #include<string.h>
    
    int N,M;
    int map[110][110],vis[110],low[110];
    int father[110];
    
    int find(int a)
    {
        if(a != father[a])
            father[a] = find(father[a]);
        return father[a];
    }
    int prim()
    {
        int pos,res = 0;
        memset(vis,0,sizeof(vis));
        vis[1] = 1;
        pos = 1;
        for(int i = 1; i <= M; i++)
            if(i != pos)
                low[i] = map[pos][i];
    
        for(int i = 1; i < M; i++)
        {
            int Min = 0xffffff0;
            for(int j = 1; j <= M; j++)
            {
                if(vis[j] == 0 && Min > low[j])
                {
                    Min = low[j];
                    pos = j;
                }
            }
            res += Min;
            vis[pos] = 1;
    
            for(int j = 1; j <= M; j++)
            {
                if(vis[j] == 0 && low[j] > map[pos][j])
                    low[j] = map[pos][j];
            }
        }
        return res;
    }
    int main()
    {
    
        int posi,posj,cost;
        while(~scanf("%d%d",&N,&M) && N!=0)
        {
            for(int i = 1; i <= M; i++)
                father[i] = i;
            for(int i = 1; i <= M; i++)
            {
                for(int j = 1; j <= M; j++)
                {
                    map[i][j] = 0xffffff0;
                }
            }
            while(N--)
            {
                scanf("%d%d%d",&posi,&posj,&cost);
                map[posi][posj] = map[posj][posi] = cost;
                int a = find(posi);
                int b = find(posj);
                if(a != b)
                {
                    father[b] = a;
                }
            }
            int a = find(1);
            int flag = 1;
            for(int i = 2; i <= M; i++)
            {
                if(find(i)!=a)
                {
                    flag = 0;
                }
            }
    
            if(flag == 0)
                printf("?

    "); else { int ans = prim(); printf("%d ",ans); } } return 0; }



  • 相关阅读:
    winform 通过左右键,或enter键做类似Tab键的功能
    向表中插入查询结果
    创建Oracle job的一些注意事项
    多数据库独立主机的配置
    图形码验证
    JavaScript中的trycatchfinally
    ASP.Net生成后台脚本的问题的解决办法
    10个你未必知道的CSS技巧
    学习JQuery的$.Ready()与OnLoad事件比较[转]
    风雨20年:我所积累的20条编程经验[csdn]
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6905644.html
Copyright © 2011-2022 走看看