atcoder-abc363_e

考点

  • 最短路

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 50, maxm = 1e6 + 50;
int n, m, p, ans, cnt[maxm], v[maxm], d[maxm], a[maxn][maxn];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
priority_queue<pair<int, int>> q;

void dijkstra() {
while (!q.empty()) {
int id = q.top().second;
q.pop();
if (v[id]) continue;
v[id] = 1;
for (int x = id / m, y = id % m, i = 0; i < 4; ++i) {
int nx = x + dx[i], ny = y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
if (d[nx * m + ny] > max(d[x * m + y], a[nx][ny])) {
d[nx * m + ny] = max(d[x * m + y], a[nx][ny]);
q.push({-d[nx * m + ny], nx * m + ny});
}
}
}
}
}

int main() {
cin >> n >> m >> p;
ans = n * m;
memset(d, 0x3f, sizeof(d));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> a[i][j];
if (i == 0 || i == n - 1 || j == 0 || j == m - 1) {
d[i * m + j] = a[i][j];
q.push({-a[i][j], i * m + j});
}
}
}
dijkstra();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cnt[d[i * m + j]]++;
}
}
for (int i = 1; i <= p; ++i) {
ans -= cnt[i];
cout << ans << endl;
}
return 0;
}

思路

网格图的广义最短路问题。把外面一圈的海洋,看作图的一个起点。

从起点走到任何一个格子,都有若干条路径;只有路径上的最大方格都被淹了,本格子才会被淹。

如图所示,第一条路径格子3被淹了才行;第二条路径格子10被淹了才行。

最短路模型中,每个方格枚举了起点走到本方格的路径长度,并保存所有路径长度中最短的。

本问题中,所谓的”路径长度“的定义,修改为”路径中的最大格子“;每个格子保存所有”路径中的最大格子“的最小值

相对于原版dijkstra,要修改的代码只有这一行:

1
d[nx * m + ny] > max(d[x * m + y], a[nx][ny])

因为还是保存最小值,依旧是大于号;修改定义即可。