#include <iostream> #include <vector> #include <map> #include <set> #include <queue> std::vector<std::vector<int>> greedy(std::vector<std::vector<bool>> const& M) { int n = M.size(); std::vector<std::vector<int>> X(n, std::vector<int>(n, -1)); std::vector<std::vector<bool>> R(n, std::vector<bool>(n)); std::vector<std::set<int>> A(n), B(n); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (!M[i][j]) { A[i].insert(j); B[j].insert(i); } } } std::priority_queue<std::pair<int, std::pair<int, int>>> Q; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (M[i][j]) { Q.push({-(A[i].size() + B[j].size()), {i, j}}); } } } while (!Q.empty()) { auto [c, p] = Q.top(); auto [x, y] = p; Q.pop(); if (R[x][y]) continue; R[x][y] = 1; if (c == 0) continue; int a, b; if (A[x].size() > B[y].size()) { a = x; b = *A[x].begin(); A[a].erase(b); B[b].erase(a); X[x][y] = 0; X[a][b] = 0; for (int k = 0; k < n; ++k) { if (!R[a][k] && M[a][k]) Q.push({-(A[a].size() + B[k].size()), {a, k}}); if (!R[k][b] && M[k][b]) Q.push({-(A[k].size() + B[b].size()), {k, b}}); } } else { a = *B[y].begin(); b = y; A[a].erase(b); B[b].erase(a); X[x][y] = 1; X[a][b] = 1; for (int k = 0; k < n; ++k) { if (!R[a][k] && M[a][k]) Q.push({-(A[a].size() + B[k].size()), {a, k}}); if (!R[k][b] && M[k][b]) Q.push({-(A[k].size() + B[b].size()), {k, b}}); } } } for (int x = 0; x < n; ++x) { for (int y = 0; y < n; ++y) { if (!M[x][y] || R[x][y]) continue; if (A[x].size() == 0 && B[y].size() == 0) continue; int a, b; if (A[x].size() > B[y].size()) { a = x; b = *A[x].begin(); A[a].erase(b); B[b].erase(a); X[x][y] = 0; X[a][b] = 0; } else { a = *B[y].begin(); b = y; A[a].erase(b); B[b].erase(a); X[x][y] = 1; X[a][b] = 1; } } } return X; } typedef std::vector<std::set<int>> Graph; std::pair<Graph, Graph> build_flow(std::vector<std::vector<bool>> const& B) { int n = B.size(); int source = 0; int io_start = 1; int d1_start = io_start + n * n; int d2_start = d1_start + n; int sink = d2_start + n; std::vector<std::vector<int>> G = greedy(B); Graph E(sink + 1), R(sink + 1); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (B[i][j]) { if (G[i][j] >= 0) R[io_start + i * n + j].insert(source); else E[source].insert(io_start + i * n + j); if (G[i][j] == 0) R[d1_start + i].insert(io_start + i * n + j); else E[io_start + i * n + j].insert(d1_start + i); if (G[i][j] == 1) R[d2_start + j].insert(io_start + i * n + j); else E[io_start + i * n + j].insert(d2_start + j); } else { if (G[i][j] == 0) R[io_start + i * n + j].insert(d1_start + i); else E[d1_start + i].insert(io_start + i * n + j); if (G[i][j] == 1) R[io_start + i * n + j].insert(d2_start + j); else E[d2_start + j].insert(io_start + i * n + j); if (G[i][j] >= 0) R[sink].insert(io_start + i * n + j); else E[io_start + i * n + j].insert(sink); } } } return {std::move(E), std::move(R)}; } void switch_position(int n, Graph& E, Graph& R, int x, int y, bool new_val) { int source = 0; int io_start = 1; int d1_start = io_start + n * n; int d2_start = d1_start + n; int sink = d2_start + n; int p = io_start + x * n + y; if (!new_val) { if (R[p].find(0) != R[p].end()) { int v2, a, b; if (R[d1_start + x].find(p) != R[d1_start + x].end()) { v2 = d1_start + x; a = x; for (b = 0; b < n; ++b) { if (R[io_start + a * n + b].find(v2) != R[io_start + a * n + b].end() && R[sink].find(io_start + a * n + b) != R[sink].end()) break; } } else { v2 = d2_start + y; b = y; for (a = 0; a < n; ++a) { if (R[io_start + a * n + b].find(v2) != R[io_start + a * n + b].end() && R[sink].find(io_start + a * n + b) != R[sink].end()) break; } } R[sink].erase(io_start + a * n + b); E[io_start + a * n + b].insert(sink); R[io_start + a * n + b].erase(v2); E[v2].insert(io_start + a * n + b); } } else { if (R[sink].find(p) != R[sink].end()) { int v2, a, b; if (R[p].find(d1_start + x) != R[p].end()) { v2 = d1_start + x; a = x; for (b = 0; b < n; ++b) { if (R[v2].find(io_start + a * n + b) != R[v2].end() && R[io_start + a * n + b].find(0) != R[io_start + a * n + b].end()) break; } } else { v2 = d2_start + y; b = y; for (a = 0; a < n; ++a) { if (R[v2].find(io_start + a * n + b) != R[v2].end() && R[io_start + a * n + b].find(0) != R[io_start + a * n + b].end()) break; } } R[io_start + a * n + b].erase(0); E[0].insert(io_start + a * n + b); R[v2].erase(io_start + a * n + b); E[io_start + a * n + b].insert(v2); } } E[0].erase(p); R[p].erase(0); E[p].erase(sink); R[sink].erase(p); E[p].erase(d1_start + x); R[p].erase(d1_start + x); E[d1_start + x].erase(p); R[d1_start + x].erase(p); E[p].erase(d2_start + y); R[p].erase(d2_start + y); E[d2_start + y].erase(p); R[d2_start + y].erase(p); if (new_val) { E[0].insert(p); E[p].insert(d1_start + x); E[p].insert(d2_start + y); } else { E[p].insert(sink); E[d1_start + x].insert(p); E[d2_start + y].insert(p); } } int flow(Graph& E, Graph& R) { int const source = 0; int const sink = E.size() - 1; while (true) { std::map<int, int> L; //std::queue<std::pair<int, int>> Q; //Q.push({source, -1}); std::vector<std::pair<int, int>> Q; Q.push_back({source, -1}); while (!Q.empty()) { //auto [p, last] = Q.front(); Q.pop(); auto [p, last] = Q.back(); Q.pop_back(); if (L.find(p) != L.end()) continue; L[p] = last; if (p == sink) break; //for (int i : E[p]) Q.push({i, p}); //for (int i : R[p]) Q.push({i, p}); for (int i : E[p]) Q.push_back({i, p}); for (int i : R[p]) Q.push_back({i, p}); } if (L.find(sink) == L.end()) break; std::vector<int> path = {sink}; while (path.back() != source) { path.push_back(L[path.back()]); } for (int i = 0; i < path.size() - 1; ++i) { int b = path[i], a = path[i + 1]; if (E[a].find(b) != E[a].end()) { E[a].erase(b); R[b].insert(a); } else { R[a].erase(b); E[b].insert(a); } } } return R[sink].size(); } int main() { std::ios::sync_with_stdio(false); int n, m, q; std::cin >> n >> m >> q; std::vector<std::vector<bool>> B(n, std::vector<bool>(n)); for (int i = 0; i < m; ++i) { int a, b, c, d; std::cin >> a >> b >> c >> d; --a; --b; --c; --d; for (int x = a; x <= c; ++x) { for (int y = b; y <= d; ++y) { B[x][y] = !B[x][y]; } } } auto [E, R] = build_flow(B); std::cout << flow(E, R) << "\n"; for (int i = 0; i < q; ++i) { int x, y; std::cin >> x >> y; --x; --y; B[x][y] = !B[x][y]; switch_position(n, E, R, x, y, B[x][y]); std::cout << flow(E, R) << "\n"; } return 0; }
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 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | #include <iostream> #include <vector> #include <map> #include <set> #include <queue> std::vector<std::vector<int>> greedy(std::vector<std::vector<bool>> const& M) { int n = M.size(); std::vector<std::vector<int>> X(n, std::vector<int>(n, -1)); std::vector<std::vector<bool>> R(n, std::vector<bool>(n)); std::vector<std::set<int>> A(n), B(n); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (!M[i][j]) { A[i].insert(j); B[j].insert(i); } } } std::priority_queue<std::pair<int, std::pair<int, int>>> Q; for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (M[i][j]) { Q.push({-(A[i].size() + B[j].size()), {i, j}}); } } } while (!Q.empty()) { auto [c, p] = Q.top(); auto [x, y] = p; Q.pop(); if (R[x][y]) continue; R[x][y] = 1; if (c == 0) continue; int a, b; if (A[x].size() > B[y].size()) { a = x; b = *A[x].begin(); A[a].erase(b); B[b].erase(a); X[x][y] = 0; X[a][b] = 0; for (int k = 0; k < n; ++k) { if (!R[a][k] && M[a][k]) Q.push({-(A[a].size() + B[k].size()), {a, k}}); if (!R[k][b] && M[k][b]) Q.push({-(A[k].size() + B[b].size()), {k, b}}); } } else { a = *B[y].begin(); b = y; A[a].erase(b); B[b].erase(a); X[x][y] = 1; X[a][b] = 1; for (int k = 0; k < n; ++k) { if (!R[a][k] && M[a][k]) Q.push({-(A[a].size() + B[k].size()), {a, k}}); if (!R[k][b] && M[k][b]) Q.push({-(A[k].size() + B[b].size()), {k, b}}); } } } for (int x = 0; x < n; ++x) { for (int y = 0; y < n; ++y) { if (!M[x][y] || R[x][y]) continue; if (A[x].size() == 0 && B[y].size() == 0) continue; int a, b; if (A[x].size() > B[y].size()) { a = x; b = *A[x].begin(); A[a].erase(b); B[b].erase(a); X[x][y] = 0; X[a][b] = 0; } else { a = *B[y].begin(); b = y; A[a].erase(b); B[b].erase(a); X[x][y] = 1; X[a][b] = 1; } } } return X; } typedef std::vector<std::set<int>> Graph; std::pair<Graph, Graph> build_flow(std::vector<std::vector<bool>> const& B) { int n = B.size(); int source = 0; int io_start = 1; int d1_start = io_start + n * n; int d2_start = d1_start + n; int sink = d2_start + n; std::vector<std::vector<int>> G = greedy(B); Graph E(sink + 1), R(sink + 1); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { if (B[i][j]) { if (G[i][j] >= 0) R[io_start + i * n + j].insert(source); else E[source].insert(io_start + i * n + j); if (G[i][j] == 0) R[d1_start + i].insert(io_start + i * n + j); else E[io_start + i * n + j].insert(d1_start + i); if (G[i][j] == 1) R[d2_start + j].insert(io_start + i * n + j); else E[io_start + i * n + j].insert(d2_start + j); } else { if (G[i][j] == 0) R[io_start + i * n + j].insert(d1_start + i); else E[d1_start + i].insert(io_start + i * n + j); if (G[i][j] == 1) R[io_start + i * n + j].insert(d2_start + j); else E[d2_start + j].insert(io_start + i * n + j); if (G[i][j] >= 0) R[sink].insert(io_start + i * n + j); else E[io_start + i * n + j].insert(sink); } } } return {std::move(E), std::move(R)}; } void switch_position(int n, Graph& E, Graph& R, int x, int y, bool new_val) { int source = 0; int io_start = 1; int d1_start = io_start + n * n; int d2_start = d1_start + n; int sink = d2_start + n; int p = io_start + x * n + y; if (!new_val) { if (R[p].find(0) != R[p].end()) { int v2, a, b; if (R[d1_start + x].find(p) != R[d1_start + x].end()) { v2 = d1_start + x; a = x; for (b = 0; b < n; ++b) { if (R[io_start + a * n + b].find(v2) != R[io_start + a * n + b].end() && R[sink].find(io_start + a * n + b) != R[sink].end()) break; } } else { v2 = d2_start + y; b = y; for (a = 0; a < n; ++a) { if (R[io_start + a * n + b].find(v2) != R[io_start + a * n + b].end() && R[sink].find(io_start + a * n + b) != R[sink].end()) break; } } R[sink].erase(io_start + a * n + b); E[io_start + a * n + b].insert(sink); R[io_start + a * n + b].erase(v2); E[v2].insert(io_start + a * n + b); } } else { if (R[sink].find(p) != R[sink].end()) { int v2, a, b; if (R[p].find(d1_start + x) != R[p].end()) { v2 = d1_start + x; a = x; for (b = 0; b < n; ++b) { if (R[v2].find(io_start + a * n + b) != R[v2].end() && R[io_start + a * n + b].find(0) != R[io_start + a * n + b].end()) break; } } else { v2 = d2_start + y; b = y; for (a = 0; a < n; ++a) { if (R[v2].find(io_start + a * n + b) != R[v2].end() && R[io_start + a * n + b].find(0) != R[io_start + a * n + b].end()) break; } } R[io_start + a * n + b].erase(0); E[0].insert(io_start + a * n + b); R[v2].erase(io_start + a * n + b); E[io_start + a * n + b].insert(v2); } } E[0].erase(p); R[p].erase(0); E[p].erase(sink); R[sink].erase(p); E[p].erase(d1_start + x); R[p].erase(d1_start + x); E[d1_start + x].erase(p); R[d1_start + x].erase(p); E[p].erase(d2_start + y); R[p].erase(d2_start + y); E[d2_start + y].erase(p); R[d2_start + y].erase(p); if (new_val) { E[0].insert(p); E[p].insert(d1_start + x); E[p].insert(d2_start + y); } else { E[p].insert(sink); E[d1_start + x].insert(p); E[d2_start + y].insert(p); } } int flow(Graph& E, Graph& R) { int const source = 0; int const sink = E.size() - 1; while (true) { std::map<int, int> L; //std::queue<std::pair<int, int>> Q; //Q.push({source, -1}); std::vector<std::pair<int, int>> Q; Q.push_back({source, -1}); while (!Q.empty()) { //auto [p, last] = Q.front(); Q.pop(); auto [p, last] = Q.back(); Q.pop_back(); if (L.find(p) != L.end()) continue; L[p] = last; if (p == sink) break; //for (int i : E[p]) Q.push({i, p}); //for (int i : R[p]) Q.push({i, p}); for (int i : E[p]) Q.push_back({i, p}); for (int i : R[p]) Q.push_back({i, p}); } if (L.find(sink) == L.end()) break; std::vector<int> path = {sink}; while (path.back() != source) { path.push_back(L[path.back()]); } for (int i = 0; i < path.size() - 1; ++i) { int b = path[i], a = path[i + 1]; if (E[a].find(b) != E[a].end()) { E[a].erase(b); R[b].insert(a); } else { R[a].erase(b); E[b].insert(a); } } } return R[sink].size(); } int main() { std::ios::sync_with_stdio(false); int n, m, q; std::cin >> n >> m >> q; std::vector<std::vector<bool>> B(n, std::vector<bool>(n)); for (int i = 0; i < m; ++i) { int a, b, c, d; std::cin >> a >> b >> c >> d; --a; --b; --c; --d; for (int x = a; x <= c; ++x) { for (int y = b; y <= d; ++y) { B[x][y] = !B[x][y]; } } } auto [E, R] = build_flow(B); std::cout << flow(E, R) << "\n"; for (int i = 0; i < q; ++i) { int x, y; std::cin >> x >> y; --x; --y; B[x][y] = !B[x][y]; switch_position(n, E, R, x, y, B[x][y]); std::cout << flow(E, R) << "\n"; } return 0; } |