Description
AKD市处在一个四面环山的谷地里。最近一场大暴雨引发了洪水,AKD市全被水淹没了。Blue Mary,AKD市的市 长,召集了他的所有顾问(包括你)参加一个紧急会议。经过细致的商议之后,会议决定,调集若干巨型抽水机, 将它们放在某些被水淹的区域,而后抽干洪水。你手头有一张AKD市的地图。这张地图是边长为m*n的矩形,被划分 为m*n个1*1的小正方形。对于每个小正方形,地图上已经标注了它的海拔高度以及它是否是AKD市的一个组成部分 。地图上的所有部分都被水淹没了。并且,由于这张地图描绘的地面周围都被高山所环绕,洪水不可能自动向外排 出。显然,我们没有必要抽干那些非AKD市的区域。每个巨型抽水机可以被放在任何一个1*1正方形上。这些巨型抽 水机将持续地抽水直到这个正方形区域里的水被彻底抽干为止。当然,由连通器原理,所有能向这个格子溢水的格 子要么被抽干,要么水位被降低。每个格子能够向相邻的格子溢水,“相邻的”是指(在同一高度水平面上的射影 )有公共边。 Input
第一行是两个数m,n(1<=m,n<=1000). 以下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
解题方法:参考PO爷的博客,OTZ PO爷
我们首先考虑如果在格子 a 修建一个抽水机,在什么情况下格子 b 的水也可以被抽干。我们可以发现当且仅当存在一条从 a 到 b 的路径,中间经过的抽水机(包括 a)的高度都不大于 b 的高度。因此我们可以考虑把所有格子的高度从小到大排序,我们把每一个格子建成一个集合。然后按照海拔高度从小到大扫描格子,对于当前的格子 i,我们找到所有与 i 相邻并且海拔高度不大于格子 i 的格子,我们发现如果这些格子中的任意一个洪水要是被解决了,那么格子 i 的洪水也可以被解决,所以我们合并这些格子。对于当前的格子 i,如果它必须被清理且与它相邻的格子集合中没有任何一个被清理,我们则把这个集合的清理状态标记为真,然后答案加 1。集合和每个格子是否被清理用并查集来维护就可以了。
代码如下:
#include <bits/stdc++.h>using namespace std;const int maxn = 1010;int n, m, tot, ans, a[maxn][maxn];int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};struct node{ int x, y, height; node(){} node(int x, int y, int height) : x(x), y(y), height(height) {} bool Operator <(const node &rhs) const{ return height < rhs.height; }}city[maxn*maxn], maze[maxn*maxn];bool flag[maxn][maxn];pair <int, int> fa[maxn][maxn];pair <int, int> find_set(pair <int, int> x){ if(x == fa[x.first][x.second] || fa[x.first][x.second] == make_pair(0, 0)) return fa[x.first][x.second] = x; else return fa[x.first][x.second] = find_set(fa[x.first][x.second]);}void union_set(pair <int, int> x, pair <int, int> y){ x = find_set(x), y = find_set(y); if(x != y){ fa[x.first][x.second] = y; flag[y.first][y.second] |= flag[x.first][x.second]; }}void cha(int x, int y){ for(int i = 0; i < 4; i++){ int tx = x + dir[i][0], ty = y + dir[i][1]; if(tx <= 0 || ty <= 0 || tx > m || ty > n) continue; if(a[tx][ty] > a[x][y]) continue; union_set(make_pair(x, y), make_pair(tx, ty)); }}int main(){ scanf("%d%d", &m, &n); for(int i = 1; i <= m; i++){ for(int j = 1; j <= n; j++){ scanf("%d", &a[i][j]); if(a[i][j] > 0) city[++tot] = node(i, j, a[i][j]); else{ a[i][j] = -a[i][j]; } maze[i*n - n + j] = node(i, j, a[i][j]); } } sort(city + 1, city + 1 + tot); sort(maze + 1, maze + 1 + n * m); for(int i = 1, j = 1; i <= tot; i++){ for(; j <= m*n && maze[j].height <= city[i].height; j++) cha(maze[j].x, maze[j].y); pair <int, int> now = find_set(make_pair(city[i].x, city[i].y)); if(flag[now.first][now.second]) continue; ++ans, flag[now.first][now.second] = 1; } PRintf("%d/n", ans); return 0;}新闻热点
疑难解答