zoukankan      html  css  js  c++  java
  • <hdu

      本题链接http://acm.hdu.edu.cn/showproblem.php?pid=1863

     Problem Description:
      省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
     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
      ?

      解题思路:村庄(支点)之间修公路,给出之间需要的的修路费(权值),如果输入的统计数据不足的话,最后输出的时候输出“?”。这道题既可以用并查集解也可以用最小生成树求解,差不多都可以算是套模板的题,只是最后输出“?”的时候需要点技巧:

     最小生成树代码

      
     1 #include <iostream>
     2 #include <algorithm>
     3 #define maxn 105
     4 #define INF 999999
     5 
     6 using namespace std;
     7 int M, N;///M是村庄数、N是道路数
     8 bool used[maxn];
     9 int cost[maxn][maxn];
    10 int mincost[maxn];
    11 
    12 int prim () {
    13     for (int i = 1; i <= M; ++i) {
    14         mincost[i] = INF;
    15         used[i] = false;
    16     }
    17     mincost[1] = 0;
    18     int res = 0;
    19     while (true) {
    20         int v = -1;
    21         for (int u = 1; u <= M; ++u) {
    22             if (!used[u] && (v == -1 || mincost[u] < mincost[v])) v = u;
    23         }
    24         if (v == -1) break;
    25         if (mincost[v] == INF) return INF;///使用这种方法检查输出"?"的情况.
    26         used[v] = true;
    27         res += mincost[v];
    28         for (int u = 1; u <= M; ++u) {
    29             mincost[u] = min (mincost[u], cost[v][u]);
    30         }
    31     }
    32     return res;
    33 }
    34 
    35 int main () {
    36     int a, b, w;
    37     while ((cin >> N) && N ) {
    38     //    int flag = 0;
    39         cin >> M;
    40         for (int i = 1;i <= M; ++i)
    41             for (int j = 1;j <= M; ++j)
    42                 cost[i][j] = INF;
    43         for (int i = 1; i <= N; ++i) {
    44             cin >> a >> b >> w;
    45             cost[b][a] = cost[a][b] = w;
    46         }
    47     /*    for (int i = 1; i <= M; ++i){
    48             for (int j = 1; j <= M; ++j) {
    49                 if (cost[i][j] == INF && i != j)
    50                     flag = 1;
    51             }//一开始是用这种方法检查单独的点的,(错误)
    52         }*/ 
    53         int res = prim ();
    54         if (res == INF)
    55             cout << "?" << endl;
    56         else 
    57             cout << res << endl;
    58     }
    59     return 0;
    60 }
    View Code

      最小生成树(输出“?”技巧):在计算的时候做一个选择的点是否是正无穷的判断(如果一个点是孤立的话,当取到最后的时候会将代码中的v赋值到那个被孤立的点,那个点没有赋值权值,所以就是正无穷)。

     并查集代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 int pre[200];
     8 struct road {    //公路的结构体
     9     int x, y, v;
    10 }ad[6000];
    11 
    12 bool cmp(road a, road b) {
    13     return a.v < b.v;
    14 }
    15 
    16 int find(int x) {    //寻找
    17     if(pre[x] != x)
    18         return pre[x] = find(pre[x]);
    19     return pre[x];
    20 }
    21 
    22 int mix(int x,int y) {        //合并
    23     int fx = find(x), fy = find(y);
    24     if(fx == fy)
    25         return 0;
    26     pre[fy] = fx;
    27     return 1;
    28 }
    29 
    30 int main() {
    31     int i, j, n, m;
    32     int ans;
    33     int count;
    34     while(~scanf("%d%d",&m,&n))    {
    35         if (m == 0)
    36             break;
    37         for(j = 0; j < m; j++)
    38             scanf("%d%d%d",&ad[j].x ,&ad[j].y,&ad[j].v);
    39         for(i = 0; i <= n; i++)
    40             pre[i] = i;
    41         ans = 0;
    42         count = 0;
    43         sort(ad, ad+m, cmp);
    44         for(i = 0; i < m; ++i) {
    45             if(count == n - 1)    break;
    46             if(mix(ad[i].x, ad[i].y)) {
    47                 ++ count;            /////在这里判断输出"?"的时候
    48                 ans = ans + ad[i].v;
    49             }
    50         }
    51         if(count != n - 1)
    52             printf("?
    ");
    53         else 
    54             printf("%d
    ",ans);
    55     }
    56     return 0;
    57 }
    View Code

      并查集(输出“?”技巧):另外定义一个变量,在计算的时候自加,最后判断和“M - 1”(M是村庄的数目)的关系,因为离散的点连成一条线之间的道路条数就是M-1。

       

       欢迎码友评论,一起成长。

  • 相关阅读:
    多年收集的一些稀有软件1
    Object-C中使用NSKeyedArchiver归档(将各种类型的对象存储到文件中)
    转-- iOS 30多个iOS常用动画,带详细注释
    转-ios设备唯一标识获取策略
    微信授权
    Windows服务Demo
    查询某个时间段在另一个时间段里面的时间
    微服务官方文档链接
    c# html 转word
    Unreal4 入门(配置)
  • 原文地址:https://www.cnblogs.com/Ddlm2wxm/p/5719553.html
Copyright © 2011-2022 走看看