zoj 3859 DoIt is Being Flooded (MFSet && Flood Fill)

本文详细解析了解决ZOJ3354问题的方法,通过调整每个grid的实际淹没时间,以及利用并查集统计块的个数来简化计算过程。代码实现清晰易懂,适合对数据结构和算法感兴趣的读者深入学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ZOJ :: Problems :: Show Problem

  这题开始的时候想不到怎么调整每个grid的实际淹没时间,于是只好找了下watashi的题解,发现这个操作还是挺简单的。

ZOJ3354 | ゆっくりでいいさ debug这题累死了。。解释还是移步看watashi大神的吧。。

  除了开始的时候这个调整,后面并查集的部分是相当容易想到的,其实就是用并查集了统计每一个块的个数。

代码如下:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <map>
  6 #include <queue>
  7 
  8 using namespace std;
  9 
 10 int n, m;
 11 inline int con(int x, int y) { return x * m + y;}
 12 inline bool inmat(int x, int y) { return 0 <= x && x < n && 0 <= y && y < m;}
 13 
 14 const int dx[4] = { 0, -1, 0, 1};
 15 const int dy[4] = { -1, 0, 1, 0};
 16 const int N = 555;
 17 const int M = N * N;
 18 
 19 struct MFS {
 20     int fa[M], cnt[M];
 21     int fx, fy;
 22     void init() { for (int i = 0; i < M; i++) fa[i] = i, cnt[i] = 1;}
 23     int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]);}
 24     void merge(int x, int y) {
 25         fx = find(x), fy = find(y);
 26         if (fx == fy) return ;
 27         fa[fy] = fx;
 28         cnt[fx] += cnt[fy];
 29     }
 30     bool same(int x, int y) { return find(x) == find(y);}
 31     int count(int x) { return cnt[find(x)];}
 32 } mfs;
 33 bool vis[N][N];
 34 int qry[11111][2], hmk[11111];
 35 
 36 struct Grid {
 37     int h, x, y;
 38     Grid() {}
 39     Grid(int h, int x, int y) : h(h), x(x), y(y) {}
 40     bool operator < (Grid a) const { return h > a.h;}
 41 } grid[M];
 42 
 43 int mat[N][N];
 44 map<int, int> id;
 45 map<int, int> cur, rec[11111];
 46 priority_queue<Grid> pq;
 47 
 48 int bitcnt(int x) {
 49     int ret = 0;
 50     for (int i = 0; i < 32; i++) if (x & 1 << i) ret++;
 51     return ret;
 52 }
 53 
 54 int main() {
 55 //    freopen("in", "r", stdin);
 56 //    freopen("out", "w", stdout);
 57     int matsz, t;
 58     int cx, cy, nx, ny;
 59     while (~scanf("%d%d", &n, &m)) {
 60         matsz = n * m, t = 0;
 61         while (!pq.empty()) pq.pop();
 62         memset(vis, 0, sizeof(vis));
 63         for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) {
 64             scanf("%d", &mat[i][j]);
 65             if (i == 0 || j == 0 || i == n - 1 || j == m - 1) {
 66                 grid[t] = Grid(mat[i][j], i, j);
 67                 pq.push(grid[t]);
 68                 t++;
 69                 vis[i][j] = true;
 70             }
 71         }
 72         while (!pq.empty()) {
 73             cx = pq.top().x, cy = pq.top().y;
 74             pq.pop();
 75             for (int i = 0; i < 4; i++) {
 76                 nx = cx + dx[i];
 77                 ny = cy + dy[i];
 78                 if (inmat(nx, ny)) {
 79                     if (vis[nx][ny]) continue;
 80                     mat[nx][ny] = max(mat[nx][ny], mat[cx][cy]);
 81                     grid[t] = Grid(mat[nx][ny], nx, ny);
 82                     pq.push(grid[t]);
 83                     t++;
 84                     vis[nx][ny] = true;
 85                 }
 86             }
 87         }
 88         sort(grid, grid + matsz);
 89         int k;
 90         scanf("%d", &k);
 91         for (int i = 0; i < k; i++) {
 92             for (int j = 0; j < 2; j++) scanf("%d", &qry[i][j]);
 93             hmk[i] = qry[i][0];
 94         }
 95         sort(hmk, hmk + k);
 96         int sz = unique(hmk, hmk + k) - hmk;
 97         reverse(hmk, hmk + sz);
 98         id.clear();
 99         cur.clear();
100         memset(vis, 0, sizeof(vis));
101         mfs.init();
102         for (int i = 0, c = 0, a, b; i < sz; i++) {
103             id[hmk[i]] = i;
104             while (c < matsz && grid[c].h > hmk[i]) {
105                 cx = grid[c].x, cy = grid[c].y;
106                 vis[cx][cy] = true;
107                 cur[1]++;
108                 for (int d = 0; d < 4; d++) {
109                     nx = cx + dx[d], ny = cy + dy[d];
110                     if (!inmat(nx, ny) || !vis[nx][ny]) continue;
111                     a = con(cx, cy), b = con(nx, ny);
112                     if (!mfs.same(a, b)) {
113                         int ca = mfs.count(a);
114                         int cb = mfs.count(b);
115                         cur[ca]--;
116                         if (cur[ca] == 0) cur.erase(ca);
117                         cur[cb]--;
118                         if (cur[cb] == 0) cur.erase(cb);
119                         mfs.merge(a, b);
120                         cur[mfs.count(a)]++;
121                     }
122                 }
123                 c++;
124             }
125             rec[i] = cur;
126         }
127         map<int, int>::iterator mii;
128         int ans, tid;
129         for (int i = 0; i < k; i++) {
130             ans = 0, tid = id[qry[i][0]];
131             for (mii = rec[tid].begin(); mii != rec[tid].end(); mii++) {
132                 ans += (*mii).second << bitcnt((*mii).first & qry[i][1]);
133             }
134             printf("%d\n", ans);
135         }
136     }
137     return 0;
138 }
View Code

 

 

转载于:https://www.cnblogs.com/LyonLys/p/zoj_3354_Lyon.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值