zoukankan      html  css  js  c++  java
  • HDU 1863 畅通工程

    Problem Description
    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。 
    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 
    行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。 
    Output
    对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。 
    SampleInput
    3 3
    1 2 1
    1 3 2
    2 3 4
    1 3
    2 3 2
    0 100
    【思路】:这题就是最小生成树的入门题,使用KRUSKAL算法,就是一个并查集的基本思想,
    先用一个sort把路径最小值进行排序,然后按选择,判断是不是在两颗树上,如果在两颗树上
    就进行合并,如果是一颗树上,那就是本来就已经联通的情况下,就可以continue掉
    可以连接的话就总的num++;
    有个不能畅通的结果,那就是每个村庄判断过去,如果不是一颗树,那就是没法联通。
    【附上代码】:
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define maxn 105
    using namespace std;
    int n,m;///n 条路,m个村庄
    
    typedef struct EDGE
    {
        int from,to;
        long long cost;
    } edge;
    bool cmp(edge a,edge b)
    {
        return a.cost<b.cost;
    }
    edge e[maxn*maxn];
    int pre[maxn];
    void Init()
    {
        for(int i=1; i<=m; i++)
            pre[i]=i;
    }
    int finds(int x)
    {
        if(pre[x]==x)
            return x;
        else
            return pre[x]=finds(pre[x]);
    }
    void unionjoin(int x,int y)
    {
        int u=finds(x);
        int v=finds(y);
        if(u==v)
            return ;
        else
            pre[u]=v;
    }
    bool same(int x,int y)
    {
        return finds(x)==finds(y);
    }
    long long kruskal()
    {
        long long ans=0;
        sort(e+1,e+1+n,cmp);
        for(int i=1; i<=n; i++)
        {
            if(!same(e[i].from,e[i].to))
            {
                unionjoin(e[i].from,e[i].to);
                ans+=e[i].cost;
            }
            else
                continue;
        }
        return ans;
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            if(n==0)break;
            for(int i=1; i<=n; i++)
            {
                scanf("%d%d%I64d",&e[i].from,&e[i].to,&e[i].cost);
            }
            Init();
            long long res;
            res=kruskal();
            for(int i=1; i<=m; i++)
            {
                if(!same(i,1))
                {
                    res=-1;
                }
            }
            if(res==-1)
                printf("?
    ");
            else
                printf("%d
    ",res);
        }
        return 0;
    }
  • 相关阅读:
    Java锁---偏向锁、轻量级锁、自旋锁、重量级锁
    Java自旋锁
    设计模式的原则
    CGLIB介绍与原理(通过继承的动态代理)
    Android Messenger
    Android AIDL的用法
    长连接和短连接和推送
    Java对称加密算法
    Android 热修复技术中的CLASS_ISPREVERIFIED问题
    Java类加载器
  • 原文地址:https://www.cnblogs.com/qq136155330/p/8638503.html
Copyright © 2011-2022 走看看