CF78E-Evacuation

  1. 分析数据

    我们可以将一个科学家可以在t分钟之内从(x0,y0)移动到(x1,y1)作为(x0,y0)在t时刻联通。

  1. 建图

    现在我们有一个网格图了,我们可以再将其转化一下。我们构造有一个源点,一个汇点,中间有两个层,每层$n^2$个节点的图。将每个点在开始时的科学家数量作为源点到这个点在第一层相应节点的边的流量。将每个点开始时的胶囊数量作为这个点在第二层所对应的节点到汇点的边的流量。若(x0,y0)和(x1,y1)在某一时刻是联通的,则将(x0,y0)在第一层所对应的节点和(x1,y1)在第二层所对应的节点连一条流量为正无穷的边。

  2. 求解

    emmm…在我们构建的新图上跑一遍网络最大流,最大流即为答案。然而,根据相关法律法规,网络流题不允许卡Dinic/ISAP/HLPP,但可以卡EK,所以还是别用EK好。

上代码:

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include <bits/stdc++.h>
using namespace std;

const int maxn = 210;

char a[maxn][maxn], ss[maxn][maxn], can[maxn][maxn][2];
int och[200][2], was[maxn][maxn], n, q[maxn][maxn];

void bfs(int x, int y, int t) {
int b, e;
b = e = 1;
och[b][0] = x;
och[b][1] = y;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int tx, ty, i, j;
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
was[i][j] = -1;
was[x][y] = 0;
while (b <= e) {
x = och[b][0];
y = och[b][1];
if (was[x][y] == t) {
++b;
continue;
}
for (i = 0; i < 4; ++i) {
tx = x + dx[i];
ty = y + dy[i];
if (tx < 0 || tx >= n || ty < 0 || ty >= n || a[tx][ty] == 'Y')
continue;
if (was[tx][ty] == -1) {
was[tx][ty] = was[x][y] + 1;
och[++e][0] = tx;
och[e][1] = ty;
}
}
++b;
}
}

struct edge {
int to;
int cap;
};

vector<edge> e;
vector<int> v[maxn];
int flag[maxn] = {0}, pos[maxn] = {0};

void addE(int from, int to, int d) {
edge ee;
ee.to = to;
ee.cap = d;
e.push_back(ee);
v[from].push_back(e.size() - 1);
ee.to = from;
ee.cap = 0;
e.push_back(ee);
v[to].push_back(e.size() - 1);
}

int s, t, mn;

bool dfs(int w) {
int i, reb, u, tmp;
flag[w] = 1;
if (w == t)
return true;
for (i = pos[w]; i < v[w].size(); i++) {
reb = v[w][i];
u = e[reb].to;
tmp = mn;
if (e[reb].cap > 0 && e[reb].cap < mn)
mn = e[reb].cap;
if (e[reb].cap > 0 && (flag[u] == 0 && dfs(u))) {
e[reb].cap -= mn;
e[reb ^ 1].cap += mn;
pos[w] = i + 1;
return true;
}
mn = tmp;
}
for (i = 0; i < pos[w]; i++) {
reb = v[w][i];
u = e[reb].to;
if (e[reb].cap > 0 && (flag[u] == 0 && dfs(u))) {
e[reb].cap -= mn;
e[reb ^ 1].cap += mn;
pos[w] = i + 1;
return true;
}
}
return false;
}

const int inf = 0x3f3f3f3f;

int flow() {
int i, fl = 1, res = 0;
while (fl) {
fl = 0;
for (i = 0; i <= t; i++) {
flag[i] = 0;
pos[i] = 0;
}
while (1) {
mn = inf;
if (!dfs(s))
break;
fl = 1;
flag[s] = flag[t] = 0;
res += mn;
}
}
return res;
}

void bfs2(int x, int y, int t) {
int fx, fy;
fx = x;
fy = y;
int cap = a[x][y] - '0';
int b, e;
b = e = 1;
och[b][0] = x;
och[b][1] = y;
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int tx, ty, i, j;
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
q[i][j] = -1;
q[x][y] = 0;
addE(fx * n + fy, fx * n + fy + n * n, cap);
while (b <= e) {
x = och[b][0];
y = och[b][1];
if (q[x][y] == t || q[x][y] == was[x][y]) {
++b;
continue;
}
for (i = 0; i < 4; ++i) {
tx = x + dx[i];
ty = y + dy[i];
if (tx < 0 || tx >= n || ty < 0 || ty >= n || a[tx][ty] == 'Z' ||
a[tx][ty] == 'Y')
continue;
if (q[tx][ty] == -1 &&
(q[x][y] + 1 <= was[tx][ty] || was[tx][ty] == -1)) {
q[tx][ty] = q[x][y] + 1;
addE(fx * n + fy, tx * n + ty + n * n, cap);
och[++e][0] = tx;
och[e][1] = ty;
}
}
++b;
}
}

int main() {
int T, i, j, x, y;
cin >> n >> T;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
cin >> a[i][j];
if (a[i][j] == 'Z') {
x = i;
y = j;
}
}
}
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
cin >> ss[i][j];
}
bfs(x, y, T);
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
if (a[i][j] >= '0' && a[i][j] <= '9') {
bfs2(i, j, T);
}
}
}
s = n * n * 2 + 1;
t = n * n * 2 + 2;
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
if (a[i][j] >= '0' && a[i][j] <= '9')
addE(s, i * n + j, a[i][j] - '0');
if (ss[i][j] >= '1' && ss[i][j] <= '9')
addE(i * n + j + n * n, t, ss[i][j] - '0');
}
}
int res = flow();
cout << res;
return 0;
}

   转载规则


《CF78E-Evacuation》 VinovnyyPoterpevshiy 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
CF82E-Corridor CF82E-Corridor
这屑题可能是计算几何题中的难得的良心题了。。。这题其实就是灯照进去每个窗的面积总和减去灯光相交、重叠部分的面积。 灯照进去每个窗的面积总和 我们很容易发现这题灯照进去每个窗的面积其实就是一个梯形的面积,这个梯形的高就是12345678
2019-09-22
下一篇 
CF73F-Plane-of-Tanks CF73F-Plane-of-Tanks
一眼二分题,check打懵逼 ——某奆佬 好吧,,,在这题中,如果$v_1 \le v_2$且$v_1$为可行解,则$v_2$必然为可行解,所以是有单调性的,所以可以二分,然后二分的check就不会打了。。 重点:关于check
2019-09-22
  目录