bzoj1104 [POI2007]洪水pow
Description
\(AKD\) 市處在一個四面環山的谷地裏。最近一場大暴雨引發了洪水,\(AKD\) 市全被水淹沒了。\(Blue\) \(Mary\),\(AKD\) 市的市長,召集了他的所有顧問(包括你)參加一個緊急會議。經過細致的商議之後,會議決定,調集若幹巨型抽水機,將它們放在某些被水淹的區域,而後抽幹洪水。你手頭有一張 \(AKD\) 市的地圖。這張地圖是邊長為 \(m*n\) 的矩形,被劃分為 \(m*n\) 個 \(1*1\) 的小正方形。對於每個小正方形,地圖上已經標註了它的海拔高度以及它是否是 \(AKD\) 市的一個組成部分。地圖上的所有部分都被水淹沒了。並且,由於這張地圖描繪的地面周圍都被高山所環繞,洪水不可能自動向外排出。顯然,我們沒有必要抽幹那些非 \(AKD\)
Input
第一行是兩個數\(m,n(1\leq m, n\leq1000)\). 以下 \(m\) 行,每行 \(n\) 個數,其絕對值表示相應格子的海拔高度;若該數為正,表示他是AKD市的一個區域;否則就不是。請大家註意:所有格子的海拔高度其絕對值不超過 \(1000\) ,且可以為零.
Output
只有一行,包含一個整數,表示至少需要放置的巨型抽水機數目。
Sample Input
6 9
-2 -2 -1 -1 -2 -2 -2 -12 -3
-2 1 -1 2 -8 -12 2 -12 -12
-5 3 1 1 -12 4 -6 2 -2
-5 -2 -2 2 -12 -3 4 -3 -1
-5 -6 -2 2 -12 5 6 2 -1
-4 -8 -8 -10 -12 -8 -6 -6 -4
Sample Output
2
Solution
\(bzoj\) 的題意果然是經常描述不清啊...
我們取出所有的城市放在 \(S\) 集合中,從小到大枚舉每個城市,從小到大排序從所有的元素中取出海拔小於等於當前城市海拔的元素,合並相鄰元素,然後查詢當前城市所在的聯通塊是否已經被覆蓋,如果沒有就在當前城市安上水泵。
#include<bits/stdc++.h>
using namespace std;
#define N 1000008
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define INF 0x7fffffff
inline int read() {
int x = 0, flag = 1; char ch = getchar(); while (!isdigit(ch)) { if (!(ch ^ '-')) flag = -1; ch = getchar(); }
while (isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar(); return x * flag;
}
const int mv[4][2] = { 1, 0, -1, 0, 0, 1, 0 ,-1 };
struct pointType {
int x, y, hei;
bool operator < (const pointType& b) const { return hei < b.hei; }
}s[N], t[N];
bool tag[N];
int h[1008][1008];
int n, m, cnt, ans;
int fa[N];
int find(int x) { return (fa[x] ^ x) ? fa[x] = find(fa[x]) : x; }
int main() {
n = read(), m = read();
rep(i, 1, n + 1) h[i][0] = h[i][m + 1] = INF; rep(i, 1, m + 1) h[0][i] = h[n + 1][i] = INF;
rep(i, 1, n * m) fa[i] = i;
rep(i, 1, n) rep(j, 1, m) {
h[i][j] = read();
if (h[i][j] > 0) s[++cnt] = pointType{ i, j, h[i][j] };
h[i][j] = abs(h[i][j]);
t[(i - 1) * m + j] = pointType{ i, j, h[i][j] };
}
sort(s + 1, s + 1 + cnt); sort(t + 1, t + 1 + n * m);
int j = 1;
rep(i, 1, cnt) {
for (; j <= m * n && t[j].hei <= s[i].hei; j++) {
int x = t[j].x, y = t[j].y;
rep(k, 0, 3) {
int nx = x + mv[k][0], ny = y + mv[k][1];
if (h[nx][ny] > h[x][y]) continue;
int f0 = find((nx - 1) * m + ny), f1 = find((x - 1) * m + y);
tag[f1] |= tag[f0], fa[f0] = f1;
}
}
int f = find((s[i].x - 1) * m + s[i].y);
if (!tag[f]) ans++, tag[f] = 1;
}
cout << ans;
return 0;
}
bzoj1104 [POI2007]洪水pow