HDU 5253 连接的管道 (最小生成树)

连接的管道

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 653    Accepted Submission(s): 268


Problem Description
老 Jack 有一片农田,以往几年都是靠天吃饭的。但是今年老天格外的不开眼,大旱。所以老 Jack 决定用管道将他的所有相邻的农田全部都串联起来,这样他就可以从远处引水过来进行灌溉了。当老 Jack 买完所有铺设在每块农田内部的管道的时候,老 Jack 遇到了新的难题,因为每一块农田的地势高度都不同,所以要想将两块农田的管道链接,老 Jack 就需要额外再购进跟这两块农田高度差相等长度的管道。

现在给出老 Jack农田的数据,你需要告诉老 Jack 在保证所有农田全部可连通灌溉的情况下,最少还需要再购进多长的管道。另外,每块农田都是方形等大的,一块农田只能跟它上下左右四块相邻的农田相连通。
 

 

Input
第一行输入一个数字T(T10),代表输入的样例组数

输入包含若干组测试数据,处理到文件结束。每组测试数据占若干行,第一行两个正整数 N,M(1N,M1000),代表老 Jack 有N行*M列个农田。接下来 N 行,每行 M 个数字,代表每块农田的高度,农田的高度不会超过100。数字之间用空格分隔。
 

 

Output
对于每组测试数据输出两行:

第一行输出:"Case #i:"。i代表第i组测试数据。

第二行输出 1 个正整数,代表老 Jack 额外最少购进管道的长度。
 

 

Sample Input
2 4 3 9 12 4 7 8 56 32 32 43 21 12 12 2 3 34 56 56 12 23 4
 

 

Sample Output
Case #1: 82 Case #2: 74
 
 
 
以高度差作为权值,跑一次最小生成树。
 
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <string>
  4 #include <queue>
  5 #include <vector>
  6 #include <map>
  7 #include <algorithm>
  8 #include <cstring>
  9 #include <cctype>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <ctime>
 13 using    namespace    std;
 14 
 15 const    int    SIZE = 1005;
 16 struct    Node
 17 {
 18     int    from,to,cost;
 19 }G[SIZE * SIZE * 2];
 20 int    MAP[SIZE][SIZE],FATHER[SIZE * SIZE];
 21 int    N,M,NUM;
 22 
 23 void    ini(void);
 24 int    find_father(int);
 25 void    unite(int,int);
 26 bool    same(int,int);
 27 bool    comp(const Node &,const Node &);
 28 long    long    kruskal(void);
 29 int    main(void)
 30 {
 31     int    t;
 32     int    count = 0;
 33 
 34     scanf("%d",&t);
 35     while(t --)
 36     {
 37         count ++;
 38         scanf("%d%d",&N,&M);
 39         ini();
 40         for(int i = 1;i <= N;i ++)
 41             for(int j = 1;j <= M;j ++)
 42                 scanf("%d",&MAP[i][j]);
 43         for(int i = 1;i <= N;i ++)
 44             for(int j = 1;j <= M;j ++)
 45             {
 46                 if(j + 1 <= M)
 47                 {
 48                     G[NUM].from = (i - 1) * M + j;
 49                     G[NUM].to = (i - 1) * M + j + 1;
 50                     G[NUM].cost = abs(MAP[i][j] - MAP[i][j + 1]);
 51                     NUM ++;
 52                 }
 53                 if(i + 1 <= N)
 54                 {
 55                     G[NUM].from = (i - 1) * M + j;
 56                     G[NUM].to = (i) * M + j;
 57                     G[NUM].cost = abs(MAP[i][j] - MAP[i + 1][j]);
 58                     NUM ++;
 59                 }
 60             }
 61         printf("Case #%d:\n%lld\n",count,kruskal());
 62     }
 63 
 64     return    0;
 65 }
 66 
 67 void    ini(void)
 68 {
 69     NUM = 0;
 70     for(int i = 1;i <= N * M;i ++)
 71         FATHER[i] = i;
 72 }
 73 
 74 int    find_father(int n)
 75 {
 76     if(n == FATHER[n])
 77         return    n;
 78     return    FATHER[n] = find_father(FATHER[n]);
 79 }
 80 
 81 void    unite(int x,int y)
 82 {
 83     x = find_father(x);
 84     y = find_father(y);
 85     
 86     if(x == y)
 87         return    ;
 88     FATHER[x] = y;
 89 }
 90 
 91 bool    same(int x,int y)
 92 {
 93     return    find_father(x) == find_father(y);
 94 }
 95 
 96 bool    comp(const Node & a,const Node & b)
 97 {
 98     return    a.cost < b.cost;
 99 }
100 
101 long    long    kruskal(void)
102 {
103     long    long    ans = 0;
104     int    count = 0;
105 
106     sort(G,G + NUM,comp);
107     for(int i = 0;i < NUM;i ++)
108         if(!same(G[i].from,G[i].to))
109         {
110             ans += G[i].cost;
111             unite(G[i].from,G[i].to);
112             if(count == N * M - 1)
113                 break;
114         }
115     return    ans;
116 }

 

posted @ 2015-06-02 16:55  Decouple  阅读(311)  评论(0编辑  收藏  举报