結果
問題 |
No.3306 Life is Easy?
|
ユーザー |
![]() |
提出日時 | 2025-10-05 16:17:19 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 778 ms / 2,000 ms |
コード長 | 3,601 bytes |
コンパイル時間 | 1,466 ms |
コンパイル使用メモリ | 124,208 KB |
実行使用メモリ | 7,716 KB |
最終ジャッジ日時 | 2025-10-05 16:17:29 |
合計ジャッジ時間 | 9,224 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 35 |
ソースコード
#include <iostream> #include <vector> #include <algorithm> #include <queue> template<typename T> class mincostflow { struct edge {int to, rep; T cap, cost; edge(int t, int r, T ca, T co) : to(t), rep(r), cap(ca), cost(co){}}; std::vector<std::vector<edge>> g; std::vector<T> h, dis; std::vector<int> prevv, preve; const T inf = (1LL << 60) | (1LL << 30); public: mincostflow(int n) : g(n), dis(n), prevv(n), preve(n) {} void add_edge(int s, int t, T cap, T cost) { g[s].emplace_back(t, (int)g[t].size(), cap, cost); g[t].emplace_back(s, (int)g[s].size() - 1, 0, -cost); } T flow(int s, int t, T f, bool isdag = false) { h.assign(g.size(), 0); if (isdag) { dis.assign(g.size(), inf); std::vector<int> inc(g.size()); for (int i = 0; i < g.size(); ++i) for (auto &e : g[i]) inc[e.to] += (e.cap > 0); std::queue<int> q; dis[s] = 0; for (int i = 0; i < g.size(); ++i) if (!inc[i]) q.push(i); while (!q.empty()) { int now = q.front(); q.pop(); for (int i = 0; i < g[now].size(); ++i) { auto &e = g[now][i]; if (e.cap == 0) continue; if (--inc[e.to] == 0) q.push(e.to); if (dis[e.to] > dis[now] + e.cost) { dis[e.to] = dis[now] + e.cost; prevv[e.to] = now; preve[e.to] = i; } } } } else dijkstra(s); T ret = 0; while (true) { if (dis[t] == inf) return inf; for (int i = 0; i < g.size(); ++i) h[i] += dis[i]; T d = f; for (int now = t; now != s; now = prevv[now]) d = std::min(d, g[prevv[now]][preve[now]].cap); f -= d; ret += d * h[t]; for (int now = t; now != s; now = prevv[now]) { g[prevv[now]][preve[now]].cap -= d; g[now][g[prevv[now]][preve[now]].rep].cap += d; } if (f <= 0) return ret; dijkstra(s); } return ret; } private: void dijkstra(int s) { dis.assign(g.size(), inf); dis[s] = 0; std::priority_queue<std::pair<T, int>, std::vector<std::pair<T, int>>, std::greater<std::pair<T, int>>> pq; pq.emplace(0, s); while (!pq.empty()) { auto [d, now] = pq.top(); pq.pop(); if (dis[now] < d) continue; for (int i = 0; i < g[now].size(); ++i) { edge &e = g[now][i]; if (e.cap > 0 && dis[e.to] > dis[now] + e.cost + h[now] - h[e.to]) { dis[e.to] = dis[now] + e.cost + h[now] - h[e.to]; prevv[e.to] = now; preve[e.to] = i; pq.emplace(dis[e.to], e.to); } } } } }; using namespace std; int main() { int n, m; cin >> n >> m; vector<vector<int>> a(n, vector<int> (m)); for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin >> a[i][j]; mincostflow<long long> mcf(n * m + 2 * n + m + 2); int sorce = n * m + 2 * n + m, sink = sorce + 1, mid = n / 2; auto cal = [&](int i, int j) -> int {return i * m + j;}; for (int i = 0; i < mid; ++i) { mcf.add_edge(sorce, n * m + i, 1, 0); for (int j = 0; j < m; ++j) { mcf.add_edge(n * m + i, cal(i, j), 1, 0); mcf.add_edge(cal(i, j), n * (m + 2) + j, 1, -(a[mid][j] - a[i][j])); } } for (int i = mid; i < n; ++i) { mcf.add_edge(n * m + i, sink, 1, 0); for (int j = 0; j < m; ++j) { mcf.add_edge(cal(i, j), n * m + i, 1, 0); mcf.add_edge(n * (m + 2) + j, cal(i, j), 1, a[mid][j] - a[i][j]); } } mcf.add_edge(sorce, sink, n, 0); long long ans = mcf.flow(sorce, sink, n); cout << -ans << endl; }