From 55f6f45c4ce1b5ce0d62d9773a65094d48eb00e2 Mon Sep 17 00:00:00 2001 From: Jaemin Choi <1dotolee@gmail.com> Date: Mon, 21 Sep 2020 23:02:14 +0900 Subject: [PATCH 1/4] Create Dinic.cpp --- Dinic.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 Dinic.cpp diff --git a/Dinic.cpp b/Dinic.cpp new file mode 100644 index 0000000..0f3b74a --- /dev/null +++ b/Dinic.cpp @@ -0,0 +1,107 @@ +#include +using namespace std; + +struct node { + int nxt, flw, rev; + node(int a, int b, int c) : nxt(a), flw(b), rev(c) {} +}; + +int T, n, m, ans, src, sink; +int board[51][51]; +int level[2550], idx[2550]; +vector> adj; +int dy[] = {1, 0, -1, 0}; +int dx[] = {0, 1, 0, -1}; + +void addEdge(int a, int b, int flow) { + adj[a].emplace_back(b, flow, adj[b].size()); + adj[b].emplace_back(a, 0, adj[a].size() - 1); +} + +bool inRange(int y, int x) { + return 0 <= y && y < n && 0 <= x && x < m; +} + +bool bfs() { + memset(level, -1, sizeof(level)); + queue q; + q.push(src); + level[src] = 0; + while (!q.empty()) { + int cur = q.front(); + q.pop(); + for (auto i : adj[cur]) { + if (level[i.nxt] == -1 && i.flw > 0) { + level[i.nxt] = level[cur] + 1; + q.push(i.nxt); + } + } + } + return level[sink] != -1; +} + +int dfs(int cur, int cap) { + if (cur == sink) return cap; + for (int &i = idx[cur]; i < adj[cur].size(); i++) { + int nxt = adj[cur][i].nxt; + int flw = adj[cur][i].flw; + if (level[cur] + 1 == level[nxt] && flw > 0) { + int val = dfs(nxt, min(cap, flw)); + if (val > 0) { + adj[cur][i].flw -= val; + adj[nxt][adj[cur][i].rev].flw += val; + return val; + } + } + } + return 0; +} + +int main() { + ios::sync_with_stdio(0), cin.tie(0); + cin >> T; + while (T--) { + cin >> n >> m; + ans = 0; + src = n * m; + sink = src + 1; + adj = vector>(n * m + 2); + + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) { + cin >> board[i][j]; + ans += board[i][j]; + } + + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) { + int cur = i * m + j; + if ((i + j) & 1) { + addEdge(src, cur, board[i][j]); + for (int d = 0; d < 4; d++) { + int ny = i + dy[d]; + int nx = j + dx[d]; + if (!inRange(ny, nx)) continue; + int ncur = ny * m + nx; + addEdge(cur, ncur, INT_MAX); + } + } else { + addEdge(cur, sink, board[i][j]); + } + } + + while (bfs()) { + memset(idx, 0, sizeof(idx)); + while (true) { + int val = dfs(src, INT_MAX); + if (!val) break; + ans -= val; + } + } + + cout << ans << '\n'; + } +} + +// 백준 11495번: 격자 0 만들기 +// https://www.acmicpc.net/problem/11495 \ No newline at end of file From 79f1508e94b29b72d74f61820a80a95f1988e42d Mon Sep 17 00:00:00 2001 From: Jaemin Choi <1dotolee@gmail.com> Date: Sun, 27 Sep 2020 00:05:30 +0900 Subject: [PATCH 2/4] Update Dinic as Struct --- Dinic.cpp | 157 +++++++++++++++++++++++------------------------------- 1 file changed, 68 insertions(+), 89 deletions(-) diff --git a/Dinic.cpp b/Dinic.cpp index 0f3b74a..a202934 100644 --- a/Dinic.cpp +++ b/Dinic.cpp @@ -1,107 +1,86 @@ #include using namespace std; -struct node { - int nxt, flw, rev; - node(int a, int b, int c) : nxt(a), flw(b), rev(c) {} -}; - -int T, n, m, ans, src, sink; -int board[51][51]; -int level[2550], idx[2550]; -vector> adj; -int dy[] = {1, 0, -1, 0}; -int dx[] = {0, 1, 0, -1}; +struct Dinic { + typedef int flow_t; -void addEdge(int a, int b, int flow) { - adj[a].emplace_back(b, flow, adj[b].size()); - adj[b].emplace_back(a, 0, adj[a].size() - 1); -} + struct Edge { + int nxt; + flow_t res; // residual flow + size_t inv; // inversed edge index + Edge(int n, flow_t r, size_t v) : nxt(n), res(r), inv(v) {} + }; -bool inRange(int y, int x) { - return 0 <= y && y < n && 0 <= x && x < m; -} + int n; + vector> adj; + vector q, lvl, start; -bool bfs() { - memset(level, -1, sizeof(level)); - queue q; - q.push(src); - level[src] = 0; - while (!q.empty()) { - int cur = q.front(); - q.pop(); - for (auto i : adj[cur]) { - if (level[i.nxt] == -1 && i.flw > 0) { - level[i.nxt] = level[cur] + 1; - q.push(i.nxt); + Dinic(int _n) { + n = _n; + adj.resize(n); + } + void add_edge(int a, int b, flow_t cap, flow_t cap_inv=0) { + adj[a].emplace_back(b, cap, adj[b].size()); + adj[b].emplace_back(a, cap_inv, adj[a].size() - 1); + } + bool assign_level(int src, int sink) { + memset(&lvl[0], 0, sizeof(lvl[0]) * n); + queue q; + q.push(src); + lvl[src] = 1; + while (!q.empty()) { + int cur = q.front(); + q.pop(); + for (auto i : adj[cur]) { + if (!lvl[i.nxt] && i.res > 0) { + lvl[i.nxt] = lvl[cur] + 1; + q.push(i.nxt); + } } } + return lvl[sink]; } - return level[sink] != -1; -} - -int dfs(int cur, int cap) { - if (cur == sink) return cap; - for (int &i = idx[cur]; i < adj[cur].size(); i++) { - int nxt = adj[cur][i].nxt; - int flw = adj[cur][i].flw; - if (level[cur] + 1 == level[nxt] && flw > 0) { - int val = dfs(nxt, min(cap, flw)); - if (val > 0) { - adj[cur][i].flw -= val; - adj[nxt][adj[cur][i].rev].flw += val; - return val; + flow_t block_flow(int cur, int sink, flow_t cur_flow) { + if (cur == sink) return cur_flow; + for (int& i = start[cur]; i < adj[cur].size(); i++) { + auto& e = adj[cur][i]; + if (e.res > 0 && lvl[e.nxt] == lvl[cur] + 1) { + if (flow_t res = block_flow(e.nxt, sink, min(e.res, cur_flow))) { + e.res -= res; + adj[e.nxt][e.inv].res += res; + return res; + } } } + return 0; } - return 0; -} + flow_t solve(int src, int sink) { + q.resize(n); + lvl.resize(n); + start.resize(n); + flow_t ans = 0; + while (assign_level(src, sink)) { + memset(&start[0], 0, sizeof(start[0]) * n); + while (flow_t flow = block_flow(src, sink, numeric_limits::max())) + ans += flow; + } + return ans; + } +}; int main() { ios::sync_with_stdio(0), cin.tie(0); - cin >> T; - while (T--) { - cin >> n >> m; - ans = 0; - src = n * m; - sink = src + 1; - adj = vector>(n * m + 2); - - for (int i = 0; i < n; i++) - for (int j = 0; j < m; j++) { - cin >> board[i][j]; - ans += board[i][j]; - } - - for (int i = 0; i < n; i++) - for (int j = 0; j < m; j++) { - int cur = i * m + j; - if ((i + j) & 1) { - addEdge(src, cur, board[i][j]); - for (int d = 0; d < 4; d++) { - int ny = i + dy[d]; - int nx = j + dx[d]; - if (!inRange(ny, nx)) continue; - int ncur = ny * m + nx; - addEdge(cur, ncur, INT_MAX); - } - } else { - addEdge(cur, sink, board[i][j]); - } - } - - while (bfs()) { - memset(idx, 0, sizeof(idx)); - while (true) { - int val = dfs(src, INT_MAX); - if (!val) break; - ans -= val; - } - } - - cout << ans << '\n'; + int n; cin >> n; + Dinic d(52); + for (int i = 0; i < n; i++) { + int k; + char c1, c2; + cin >> c1 >> c2 >> k; + int a = islower(c1) ? c1 - 'a' + 26 : c1 - 'A'; + int b = islower(c2) ? c2 - 'a' + 26 : c2 - 'A'; + d.add_edge(a, b, k, k); } + cout << d.solve(0, 25) << endl; } -// 백준 11495번: 격자 0 만들기 -// https://www.acmicpc.net/problem/11495 \ No newline at end of file +// 백준 6086번: 최대 유량 \ No newline at end of file From 64ccba22cf664d046509bb738fb5c241387bce2a Mon Sep 17 00:00:00 2001 From: Jaemin Choi <1dotolee@gmail.com> Date: Sun, 27 Sep 2020 00:37:30 +0900 Subject: [PATCH 3/4] Fix variable 'q' in Dinic --- Dinic.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/Dinic.cpp b/Dinic.cpp index a202934..48fe555 100644 --- a/Dinic.cpp +++ b/Dinic.cpp @@ -24,21 +24,20 @@ struct Dinic { adj[b].emplace_back(a, cap_inv, adj[a].size() - 1); } bool assign_level(int src, int sink) { + int t = 0; memset(&lvl[0], 0, sizeof(lvl[0]) * n); - queue q; - q.push(src); lvl[src] = 1; - while (!q.empty()) { - int cur = q.front(); - q.pop(); - for (auto i : adj[cur]) { - if (!lvl[i.nxt] && i.res > 0) { - lvl[i.nxt] = lvl[cur] + 1; - q.push(i.nxt); + q[t++] = src; + for (int h = 0; h < t && !lvl[sink]; h++) { + int cur = q[h]; + for (auto& e : graph[cur]) { + if (l[e.nxt] == 0 && e.res > 0) { + lvl[e.nxt] = l[cur] + 1; + q[t++] = e.nxt; } } } - return lvl[sink]; + return lvl[sink] != 0; } flow_t block_flow(int cur, int sink, flow_t cur_flow) { if (cur == sink) return cur_flow; From b9b8cf2233c5d069abc107bd75326f135b11440b Mon Sep 17 00:00:00 2001 From: Jaemin Choi <1dotolee@gmail.com> Date: Sun, 27 Sep 2020 00:52:16 +0900 Subject: [PATCH 4/4] Delete needless lines --- Dinic.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/Dinic.cpp b/Dinic.cpp index 48fe555..2b63897 100644 --- a/Dinic.cpp +++ b/Dinic.cpp @@ -1,6 +1,3 @@ -#include -using namespace std; - struct Dinic { typedef int flow_t; @@ -65,21 +62,4 @@ struct Dinic { } return ans; } -}; - -int main() { - ios::sync_with_stdio(0), cin.tie(0); - int n; cin >> n; - Dinic d(52); - for (int i = 0; i < n; i++) { - int k; - char c1, c2; - cin >> c1 >> c2 >> k; - int a = islower(c1) ? c1 - 'a' + 26 : c1 - 'A'; - int b = islower(c2) ? c2 - 'a' + 26 : c2 - 'A'; - d.add_edge(a, b, k, k); - } - cout << d.solve(0, 25) << endl; -} - -// 백준 6086번: 최대 유량 \ No newline at end of file +}; \ No newline at end of file