Submission #207883

#TimeUsernameProblemLanguageResultExecution timeMemory
207883opukittpceno_hhrDango Maker (JOI18_dango_maker)C++17
33 / 100
538 ms262148 KiB
#include <iostream> #include <vector> #include <map> #include <set> #include <queue> #include <algorithm> #include <string> #include <cmath> #include <cstdio> #include <iomanip> #include <fstream> #include <cassert> #include <cstring> #include <unordered_set> #include <unordered_map> #include <numeric> #include <ctime> #include <bitset> #include <complex> #include <random> using namespace std; const int N = 3001; struct Edge { int u, v; int cap, flow; Edge(int u_, int v_, int flow_, int cap_) { u = u_; v = v_; cap = cap_; flow = flow_; } }; namespace Flow { const int INF = 1e9 + 239; const int MAX_LOG = 2; int n; int start; int end; int d[N * N]; int pnt[N * N]; vector<Edge> ed; vector<vector<int>> g; int dfs(int u, int flow) { if (flow == 0) { return 0; } if (u == end) { return flow; } for (; pnt[u] < (int)g[u].size(); pnt[u]++) { int ind = g[u][pnt[u]]; int to = ed[ind].v; if (d[to] < d[u] + 1) { continue; } int pushed = dfs(to, min(flow, ed[ind].cap - ed[ind].flow)); if (pushed > 0) { ed[ind].flow += pushed; ed[ind ^ 1].flow -= pushed; return pushed; } } return 0; } bool bfs(int lim) { for (int i = 0; i < n; i++) { d[i] = INF; } d[start] = 0; queue<int> q; q.push(start); while (!q.empty()) { int u = q.front(); q.pop(); for (auto ind : g[u]) { int to = ed[ind].v; if (d[to] > d[u] + 1 && ed[ind].flow + lim <= ed[ind].cap) { d[to] = d[u] + 1; q.push(to); } } } return d[end] != INF; } void init() { fill(pnt, pnt + n, 0); fill(d, d + n, 0); g.resize(n); } int solve() { int ans = 0; int cur = (1LL << MAX_LOG); for (int i = 0; i < MAX_LOG; i++) { cur /= 2; while (bfs(cur)) { fill(pnt, pnt + n, 0); while (true) { int nw = dfs(start, INF); ans += nw; if (nw == 0) { break; } } } } return ans; } void add_edge(int u, int v, int c) { int pnt = (int)ed.size(); ed.push_back(Edge(u, v, 0, c)); ed.push_back(Edge(v, u, 0, 0)); g[u].push_back(pnt); g[v].push_back(pnt + 1); } }// namespace Flow int a[N][N]; int read() { char c; cin >> c; if (c == 'R') return 0; if (c == 'G') return 1; if (c == 'W') return 2; assert(false); return -1; } int n, m; int ok(int i, int j, int dir) { if (dir == 0) { if (i == 0 || i + 1 == n) return 0; return a[i - 1][j] == 0 && a[i][j] == 1 && a[i + 1][j] == 2; } else { if (j == 0 || j + 1 == m) return 0; return a[i][j - 1] == 0 && a[i][j] == 1 && a[i][j + 1] == 2; } } vector<pair<int, int>> gt(int i, int j, int dir) { if (dir == 0) { return {{i - 1, j}, {i, j}, {i + 1, j}}; } else { return {{i, j - 1}, {i, j}, {i, j + 1}}; } } bool inter(vector<pair<int, int>> &x, vector<pair<int, int>> &y) { for (auto f : x) { for (auto s : y) { if (f == s) return 1; } } return 0; } vector<vector<int>> g; int used[N * N]; int clr[N * N]; int mt[N * N]; void dfs(int v, int c) { clr[v] = c; used[v] = 1; for (auto t : g[v]) { if (!used[t]) dfs(t, c ^ 1); } } int sm(int v, int timer) { if (used[v] == timer) return 0; used[v] = timer; for (auto t : g[v]) { if (mt[t] == -1 || sm(mt[t], timer)) { mt[t] = v; return 1; } } return 0; } void dfs2(int v) { used[v] = 1; for (auto t : g[v]) { if (mt[t] == v) continue; used[t] = 1; if (mt[t] != -1 && !used[mt[t]]) dfs2(mt[t]); } } void init_matching(int f) { Flow::n = f + 2; Flow::end = f + 1; Flow::start = f; Flow::init(); // cerr << "flow init ok" << endl; vector<int> we(f); for (int i = 0; i < f; i++) { for (auto j : g[i]) { if (!clr[i]) { Flow::add_edge(i, j, 1); if (!we[i]) Flow::add_edge(f, i, 1); we[i] = 1; if (!we[j]) Flow::add_edge(j, f + 1, 1); we[j] = 1; } } } Flow::solve(); fill(mt, mt + f, -1); for (auto t : Flow::ed) { if (t.flow == 1 && t.v < f && t.u < f) { mt[t.v] = t.u; } } } int solve_mathing() { int f = (int)g.size(); for (int i = 0; i < f; i++) { if (!used[i]) dfs(i, 0); } init_matching(f); fill(used, used + f, 0); vector<int> ns(f); for (int i = 0; i < f; i++) { if (mt[i] != -1) { ns[mt[i]] = 1; } } for (int i = 0; i < f; i++) { if (!clr[i] && !ns[i]) { dfs2(i); } } int ans = 0; for (int i = 0; i < f; i++) { ans += (used[i] && !clr[i]); } for (int i = 0; i < f; i++) { ans += (!used[i] && clr[i]); } return ans; } vector<int> cd[N][N]; signed main() { ios_base::sync_with_stdio(false); cin.tie(0); cin >> n >> m; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { a[i][j] = read(); } } vector<int> tk; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (ok(i, j, 0)) { tk.push_back({i * m + j}); cd[i][j].push_back((int)tk.size() - 1); } if (ok(i, j, 1)) { tk.push_back({i * m + j + n * m}); cd[i][j].push_back((int)tk.size() - 1); } } } auto get = [&](int x) { int v = tk[x]; int tp = (v / (n * m)); v %= n * m; int i = v / m; int j = v % m; return gt(i, j, tp); }; g.resize(tk.size()); for (int i = 0; i < (int)tk.size(); i++) { int v = (tk[i] % (n * m)); int ri = v / m; int rj = v % m; for (int ti = ri - 1; ti <= ri + 1; ti++) { for (int tj = rj - 1; tj <= rj + 1; tj++) { if (ti < 0 || tj < 0 || ti >= n || tj >= m) continue; for (auto j : cd[ti][tj]) { if (i == j) continue; vector<pair<int, int>> f = get(i); vector<pair<int, int>> s = get(j); if (inter(f, s)) { g[i].push_back(j); } } } } } cout << solve_mathing() << endl; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...