結果
| 問題 |
No.1479 Matrix Eraser
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2022-07-30 12:41:37 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 9,698 bytes |
| コンパイル時間 | 3,681 ms |
| コンパイル使用メモリ | 244,792 KB |
| 最終ジャッジ日時 | 2025-01-30 16:36:59 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 33 TLE * 6 |
ソースコード
#pragma region template
#include <bits/stdc++.h>
#include <atcoder/dsu>
#include <atcoder/maxflow>
using namespace std;
// clang-format off
using ll = long long; using vl = vector<ll>; using vvl = vector<vl>;
using ld = long double; using vld = vector<ld>; using vvld = vector<vld>;
using pll = pair<ll, ll>; using vpll = vector<pll>; using vvpll = vector<vpll>;
using vb = vector<bool>; using vvb = vector<vector<bool>>;
using vs = vector<string>;
using mll = map<ll, ll>;
template <class T> using V = vector<T>; template <class T> using VV = V<V<T>>; template <class T> using VVV = V<VV<T>>;
template <class T> using max_heap = priority_queue<T>;
template <class T> using min_heap = priority_queue<T, vector<T>, greater<T>>;
constexpr ll inf = 3001001000100100100LL;
#define endl '\n'
#define _overload(_1, _2, _3, name, ...) name
#define rep(...) _overload(__VA_ARGS__, _rep, _rep2,)(__VA_ARGS__)
#define repc(...) _overload(__VA_ARGS__, _repc, _repc2,)(__VA_ARGS__)
#define repr(...) _overload(__VA_ARGS__, _repr, _repr2,)(__VA_ARGS__)
#define reprc(...) _overload(__VA_ARGS__, _reprc, _reprc2,)(__VA_ARGS__)
#define _rep(i,k,n) for(ll i=(k) , i##_xxxx=(n); i < i##_xxxx; ++i)
#define _repc(i,k,n) for(ll i=(k) , i##_xxxx=(n); i <=i##_xxxx; ++i)
#define _repr(i,k,n) for(ll i=(n)-1, i##_xxxx=(k); i >=i##_xxxx; --i)
#define _reprc(i,k,n) for(ll i=(n) , i##_xxxx=(k); i >=i##_xxxx; --i)
#define _rep2(i,n) _rep(i,0,n)
#define _repc2(i,n) _repc(i,1,n)
#define _repr2(i,n) _repr(i,0,n)
#define _reprc2(i,n) _reprc(i,1,n)
#define rall(o) rbegin(o), rend(o)
#define all(o) begin(o), end(o)
template <class C> ll sz(const C& c) { return static_cast<ll>(c.size()); }
template <class T> bool chmax(T& m, const T& v){ if (m < v){ m = v; return true; } return false; }
template <class T> bool chmin(T& m, const T& v){ if (v < m){ m = v; return true; } return false; }
template <class T> T cdiv(const T& a, const T& b){ return (a + b - 1) / b; }
template <class T> T rdiv(const T& a, const T& b){ return (a + b / 2) / b; }
template <class T, class S> string join(const T& v, const S& sep ){ stringstream ss; bool f = false; for (const auto& e : v){ if (f) ss << sep; f = true; ss << e;} return ss.str(); }
template <class T, class S, class... U> string join(const T& v, const S& sep, const U& ...args){ stringstream ss; bool f = false; for (const auto& c : v){ if (f) ss << sep; f = true; ss << join(c, args...); } return ss.str(); }
ostream& operator<<(ostream& os, const __int128_t& val){ os << (ll)val; return os; }
// template <class Cap, class Edge = typename atcoder::mf_graph<Cap>::edge>
ostream& operator<<(ostream& os, const atcoder::mf_graph<__int128>::edge& e) {
auto [from, to, cap, flow] = e;
os << '(' << from << "->" << to << " : " << flow << "/" << cap << ')';
return os;
}
template <class T> ostream& operator<<(ostream& os, const vector<T>& seq){ os << '[' << join(seq, ",") << ']'; return os; }
template <class T> ostream& operator<<(ostream& os, const vector<vector<T>>& seq){ os << '[' << join(seq, ",\n ") << ']'; return os; }
template <class T> ostream& operator<<(ostream& os, const deque<T>& seq){ os << '[' << join(seq, ",") << ']'; return os; }
template <class T> ostream& operator<<(ostream& os, const set<T>& seq){ os << '{' << join(seq, ",") << '}'; return os; }
template <class T , class TH> ostream& operator<<(ostream& os, const unordered_set<T, TH>& seq){ os << '{' << join(seq, ",") << '}'; return os; }
template <class TK, class TV> ostream& operator<<(ostream& os, const map<TK, TV>& seq){ os << '{'; bool f = false; for (const auto& e : seq){ if (f) os << ','; f = true; os << e.first << ":" << e.second; } os << '}'; return os; }
template <class T1, class T2> ostream& operator<<(ostream& os, const pair<T1, T2>& pa){ os << '(' << pa.first << ',' << pa.second << ')'; return os; }
#if LOCAL
#define _overload5(_1, _2, _3, _4, _5, name, ...) name
#define debug(...) _overload5(__VA_ARGS__, _d5, _d4, _d3, _d2, _d1, )(__VA_ARGS__)
#define _pp0(x, ...) #x " =", x
#define _pp(x, ...) ", "#x " =", x
// ,pp(__VA_ARGS__)
#define _d1(x1) _debug(_pp0(x1), __LINE__)
#define _d2(x1, x2) _debug(_pp0(x1), _pp(x2), __LINE__)
#define _d3(x1, x2, x3) _debug(_pp0(x1), _pp(x2), _pp(x3), __LINE__)
// #define debug(...) _debug(__VA_ARGS__, __LINE__)
#else
#define debug(...)
#endif
void print() { std::cout << '\n'; }
template <class S> void print(const S& a){ std::cout << a << '\n'; }
template <class S> void _debug(const S& a){ std::cerr << "(L:" << std::setw(3) << a << ")\n"; }
template <class S, class... T> void print(const S& a, const T&... args){ std::cout << a << ' '; print(args...); }
template <class S, class... T> void _debug(const S& a, const T&... args){ std::cerr << a << ' '; _debug(args...); }
struct setup_main { setup_main() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); std::cout << fixed << setprecision(15); } } setup_main_;
// clang-format on
#pragma endregion
template <class Cost>
struct PSP {
struct Variable {
ll id, flip;
Variable(ll i = 0, bool f = false) : id(i), flip(f) {}
Variable operator~() { return Variable(id, !flip); }
};
using S = Variable;
ll n;
vector<vector<Cost>> cost1;
vector<vector<vector<vector<Cost>>>> cost2;
vector<Variable> var;
PSP(){};
PSP(ll n_) : n(n_) {
cost1.resize(n, vector<Cost>(2, 0));
cost2.resize(n, vector(n, vector(2, vector<Cost>(2, 0))));
var.reserve(n);
rep(i, n) var.emplace_back(i);
};
void add_constraint(S x, Cost cost) { cost1[x.id][!x.flip] += cost; }
void add_constraint(S x, S y, Cost cost) {
if (x.id > y.id) swap(x, y), cost = -cost;
cost2[x.id][y.id][!x.flip][!y.flip] += cost;
};
Cost solve() {
Cost sum = 0;
// find flips
vector<vector<Cost>> cost2_rest(n, vector<Cost>(n));
atcoder::dsu d(2 * n);
rep(i, n) rep(j, n) {
vector<vector<Cost>>& v(cost2[i][j]);
Cost c = v[0][1] + v[1][0] - v[0][0] - v[1][1];
cost1[i][0] += v[0][0];
cost1[i][1] += v[1][0];
if (c < 0) {
cost1[j][1] += v[0][1] - v[0][0];
cost2_rest[i][j] -= c;
} else {
cost1[j][1] += v[1][1] - v[1][0];
cost2_rest[i][j] += c;
}
if (c > 0) { // 劣モジュラ
d.merge(i, j);
d.merge(i + n, j + n);
} else if (c < 0) { // 非劣モジュラ
d.merge(i, n + j);
d.merge(n + i, j);
} // c=0ならflipは自由
}
rep(i, n) if (d.same(i, n + i)) return -1;
vl flip(2 * n, -1);
rep(i, 2 * n) {
ll p = d.leader(i);
if (flip[p] == -1) flip[p] = 0;
flip[i] = flip[p];
flip[d.leader((n + i) % (2 * n))] = 1 - flip[p];
debug(flip, i);
}
debug(sum);
debug(flip);
debug(cost1);
debug(cost2_rest);
// min-cut
atcoder::mf_graph<Cost> graph(n + 2);
ll s = n, t = n + 1;
rep(i, n) { // cost1
if (!flip[i]) swap(cost1[i][0], cost1[i][1]);
if (cost1[i][0] >= cost1[i][1]) {
graph.add_edge(s, i, cost1[i][0] - cost1[i][1]);
sum += cost1[i][1];
} else {
graph.add_edge(i, t, cost1[i][1] - cost1[i][0]);
sum += cost1[i][0];
}
}
rep(i, n) rep(j, n) {
if (flip[j])
graph.add_edge(i, j, cost2_rest[i][j]);
else
graph.add_edge(i, j, -cost2_rest[i][j]);
}
ll f = graph.flow(s, t);
debug(sum, f);
debug(graph.edges());
debug(graph.min_cut(s));
return sum + f;
}
};
template <class T>
struct Compress {
vector<T> inv;
Compress(vector<T> a = {}) : inv(a) {}
void push(T val) { inv.push_back(val); }
void compress() {
sort(all(inv));
inv.erase(unique(all(inv)), inv.end());
}
ll zip(T val) { return lower_bound(all(inv), val) - inv.begin(); }
T unzip(ll idx) {
assert(0 <= idx and idx < sz(inv));
return inv[idx];
}
size_t size() { return inv.size(); }
};
#ifdef LOCAL
const ll M = 10;
#else
const ll M = 500000;
#endif
void solve(ll H, ll W, vector<vector<ll>>& A) {
vvpll B(M + 1);
rep(y, H) rep(x, W) {
if (A[y][x] != 0) B[A[y][x]].emplace_back(y, x);
}
ll ans = 0;
for (auto& v : B) {
if (sz(v) == 0) continue;
if (sz(v) == 1) {
ans++;
continue;
}
Compress<ll> row, col;
for (auto&& [y, x] : v) {
row.push(y);
col.push(x);
}
row.compress(), col.compress();
ll h = row.size(), w = col.size();
PSP<ll> psp(h + w);
auto var = psp.var;
rep(y, h) psp.add_constraint(y, 1);
rep(x, w) psp.add_constraint(x + h, 1);
for (auto [y, x] : v) {
y = row.zip(y);
x = col.zip(x);
psp.add_constraint({y, false}, {x + h, false}, 1);
}
ans += (ll)psp.solve();
}
print(ans);
}
int main() {
ll H, W;
cin >> H >> W;
vector<vector<ll>> A(H, vector<ll>(W));
rep(j, H) {
rep(i, W) {
cin >> A[j][i];
}
}
solve(H, W, A);
return 0;
}