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 }

 

你可能感兴趣的:(最小生成树)