标签:
1 /*
2 最小生成树(Kruskal):以权值为头,带入两个端点,自然的排序;感觉结构体的并查集很好看
3 注意:题目老头要的是两个农田的高度差,中文水平不好,题意理解成和平均值的高度差!
4 */
5 #include <cstdio>
6 #include <algorithm>
7 #include <cstring>
8 #include <cmath>
9 #include <vector>
10 #include <queue>
11 #include <set>
12 using namespace std;
13
14 const int MAXN = 1e3 + 10;
15 const int MAXM = 1e2 + 10;
16 const int INF = 0x3f3f3f3f;
17 int n, m;
18 int a[MAXN][MAXN];
19 vector<pair<int, int> > G[MAXM];
20 struct UF
21 {
22 int rt[MAXN*MAXN];
23 void init(void) {memset (rt, -1, sizeof (rt));}
24
25 int Find(int x) {return (rt[x] == -1) ? x : rt[x] = Find (rt[x]);}
26
27 void Union(int x, int y)
28 {
29 x = Find (x); y = Find (y);
30 if (x > y) rt[y] = x;
31 else if (x < y) rt[x] = y;
32 }
33
34 bool same(int x, int y) {return Find (x) == Find (y);}
35 }uf;
36
37 int Kruskal(void)
38 {
39 uf.init ();
40 int ans = 0;
41 for (int i=0; i<=100; ++i)
42 {
43 for (int j=0; j<G[i].size (); ++j)
44 {
45 int u = G[i][j].first; int v = G[i][j].second;
46 if (!uf.same (u, v)) {uf.Union (u, v); ans += i;}
47 }
48 }
49
50 return ans;
51 }
52
53 int get_id(int i, int j) {return (i - 1) * m + j;}
54
55 int main(void) //2015百度之星初赛2 HDOJ 5253 连接的管道
56 {
57 int t, cas = 0; scanf ("%d", &t);
58 while (t--)
59 {
60 scanf ("%d%d", &n, &m);
61 for (int i=0; i<=100; ++i) G[i].clear ();
62
63 for (int i=1; i<=n; ++i)
64 {
65 for (int j=1; j<=m; ++j)
66 {
67 scanf ("%d", &a[i][j]);
68 if (i > 1) {G[abs (a[i][j] - a[i-1][j])].push_back (make_pair (get_id (i, j), get_id (i-1, j)));}
69 if (j > 1) {G[abs (a[i][j] - a[i][j-1])].push_back (make_pair (get_id (i, j), get_id (i, j-1)));}
70 }
71 }
72
73 printf ("Case #%d:\n", ++cas);
74 printf ("%d\n", Kruskal ());
75 }
76
77 return 0;
78 }
79
80
81 /*
82 2
83 4 3
84 9 12 4
85 7 8 56
86 32 32 43
87 21 12 12
88 2 3
89 34 56 56
90 12 23 4
91 */
Kruskal 2015百度之星初赛2 HDOJ 5253 连接的管道
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4544526.html