結果
| 問題 | No.957 植林 |
| コンテスト | |
| ユーザー |
hitonanode
|
| 提出日時 | 2021-08-25 03:38:14 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 172 ms / 2,000 ms |
| コード長 | 3,431 bytes |
| 記録 | |
| コンパイル時間 | 3,281 ms |
| コンパイル使用メモリ | 266,600 KB |
| 実行使用メモリ | 9,660 KB |
| 最終ジャッジ日時 | 2024-11-15 18:52:31 |
| 合計ジャッジ時間 | 7,615 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 45 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using lint = long long int;
#define ALL(x) (x).begin(), (x).end()
#define FOR(i, begin, end) for (int i = (begin), i##_end_ = (end); i < i##_end_; i++)
#define REP(i, n) FOR(i, 0, n)
template <class Cap, Cap INF = std::numeric_limits<Cap>::max() / 2> struct mf_pushrelabel {
int _n;
struct _edge {
int to, rev;
Cap cap;
};
std::vector<std::vector<_edge>> g;
std::vector<std::pair<int, int>> pos;
mf_pushrelabel(int n) : _n(n), g(n) { static_assert(INF > 0, "INF must be positive."); }
int add_edge(int from, int to, Cap cap) {
assert(0 <= from and from < _n);
assert(0 <= to and to < _n);
assert(0 <= cap);
int m = int(pos.size());
pos.emplace_back(from, int(g[from].size()));
int from_id = g[from].size(), to_id = g[to].size() + (from == to);
g[from].push_back({to, to_id, cap});
g[to].push_back({from, from_id, Cap(0)});
return m;
}
std::vector<int> dist;
std::vector<Cap> excess;
std::vector<std::vector<int>> h2v;
int max_height;
void activate(int i) {
h2v[dist[i]].push_back(i);
if (dist[i] > max_height) max_height = dist[i];
}
Cap flow(int s, int t) {
assert(0 <= s and s < _n);
assert(0 <= t and t < _n);
assert(s != t);
dist.assign(_n, 0);
dist[s] = _n;
excess.assign(_n, 0);
excess[s] = INF, excess[t] = -INF;
h2v.assign(_n * 2, {});
max_height = -1;
for (auto &e : g[s]) push(s, e);
while (max_height >= 0) {
if (h2v[max_height].empty()) {
max_height--;
continue;
}
int i = h2v[max_height].back();
h2v[max_height].pop_back();
int dnxt = _n * 2 - 1;
for (auto &e : g[i]) {
if (!e.cap) continue;
if (dist[e.to] == dist[i] - 1) {
push(i, e);
if (excess[i] == 0) break;
} else {
if (dist[e.to] + 1 < dnxt) dnxt = dist[e.to] + 1;
}
}
if (excess[i] > 0) {
dist[i] = dnxt;
activate(i);
}
}
return INF - excess[s];
}
void push(int i, _edge &e) {
Cap delta = e.cap < excess[i] ? e.cap : excess[i];
excess[i] -= delta, e.cap -= delta;
excess[e.to] += delta, g[e.to][e.rev].cap += delta;
if (excess[e.to] > 0 and excess[e.to] <= delta) activate(e.to);
}
};
int main() {
cin.tie(nullptr), ios::sync_with_stdio(false);
int H, W;
cin >> H >> W;
vector<vector<lint>> G(H, vector<lint>(W));
for (auto &v : G) {
for (auto &x : v) cin >> x;
}
vector<lint> R(H), C(W);
for (auto &x : R) cin >> x;
for (auto &x : C) cin >> x;
lint tot = accumulate(ALL(R), 0LL) + accumulate(ALL(C), 0LL);
vector<lint> EW(W);
lint f1 = 0;
int Z = 1 + H + W;
mf_pushrelabel<long long> g(Z + 1);
REP(i, H) {
lint gtot = accumulate(ALL(G[i]), 0LL);
lint f0 = min(gtot, R[i]);
f1 += f0;
g.add_edge(0, i + 1, gtot - f0);
}
REP(j, W) g.add_edge(H + 1 + j, Z, C[j]);
REP(i, H) REP(j, W) g.add_edge(i + 1, H + 1 + j, G[i][j]);
lint f2 = g.flow(0, Z);
cout << tot - f1 - f2 << endl;
}
hitonanode