結果
問題 | No.1479 Matrix Eraser |
ユーザー | tonegawa |
提出日時 | 2024-11-12 06:34:30 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 222 ms / 3,000 ms |
コード長 | 9,542 bytes |
コンパイル時間 | 3,327 ms |
コンパイル使用メモリ | 205,896 KB |
実行使用メモリ | 28,816 KB |
最終ジャッジ日時 | 2024-11-12 06:34:41 |
合計ジャッジ時間 | 10,183 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 3 ms
5,248 KB |
testcase_05 | AC | 2 ms
5,248 KB |
testcase_06 | AC | 2 ms
5,248 KB |
testcase_07 | AC | 22 ms
6,144 KB |
testcase_08 | AC | 36 ms
8,456 KB |
testcase_09 | AC | 79 ms
14,584 KB |
testcase_10 | AC | 159 ms
24,872 KB |
testcase_11 | AC | 94 ms
16,356 KB |
testcase_12 | AC | 30 ms
7,436 KB |
testcase_13 | AC | 36 ms
8,476 KB |
testcase_14 | AC | 28 ms
7,400 KB |
testcase_15 | AC | 8 ms
5,248 KB |
testcase_16 | AC | 31 ms
8,056 KB |
testcase_17 | AC | 200 ms
28,812 KB |
testcase_18 | AC | 210 ms
28,808 KB |
testcase_19 | AC | 198 ms
28,812 KB |
testcase_20 | AC | 199 ms
28,812 KB |
testcase_21 | AC | 222 ms
28,808 KB |
testcase_22 | AC | 201 ms
28,816 KB |
testcase_23 | AC | 202 ms
28,680 KB |
testcase_24 | AC | 195 ms
28,688 KB |
testcase_25 | AC | 199 ms
28,680 KB |
testcase_26 | AC | 197 ms
28,808 KB |
testcase_27 | AC | 174 ms
14,548 KB |
testcase_28 | AC | 166 ms
14,676 KB |
testcase_29 | AC | 164 ms
14,676 KB |
testcase_30 | AC | 158 ms
14,548 KB |
testcase_31 | AC | 166 ms
14,676 KB |
testcase_32 | AC | 76 ms
12,116 KB |
testcase_33 | AC | 77 ms
12,112 KB |
testcase_34 | AC | 79 ms
12,240 KB |
testcase_35 | AC | 77 ms
12,240 KB |
testcase_36 | AC | 82 ms
12,240 KB |
testcase_37 | AC | 17 ms
5,248 KB |
testcase_38 | AC | 159 ms
28,688 KB |
testcase_39 | AC | 157 ms
28,688 KB |
testcase_40 | AC | 2 ms
5,248 KB |
コンパイルメッセージ
main.cpp: In member function 'std::vector<std::pair<bool, int> > hopcroft_karp::max_independent_set()': main.cpp:294:5: warning: no return statement in function returning non-void [-Wreturn-type] 294 | } | ^
ソースコード
#include <iostream> #include <string> #include <vector> #include <array> #include <tuple> #include <stack> #include <queue> #include <deque> #include <algorithm> #include <set> #include <map> #include <unordered_set> #include <unordered_map> #include <bitset> #include <cmath> #include <functional> #include <cassert> #include <climits> #include <iomanip> #include <numeric> #include <memory> #include <random> #include <thread> #include <chrono> #define allof(obj) (obj).begin(), (obj).end() #define range(i, l, r) for(int i=l;i<r;i++) #define unique_elem(obj) obj.erase(std::unique(allof(obj)), obj.end()) #define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S) #define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit)) #define bit_kth(i, k) ((i >> k)&1) #define bit_highest(i) (i?63-__builtin_clzll(i):-1) #define bit_lowest(i) (i?__builtin_ctzll(i):-1) #define sleepms(t) std::this_thread::sleep_for(std::chrono::milliseconds(t)) using ll = long long; using ld = long double; using ul = uint64_t; using pi = std::pair<int, int>; using pl = std::pair<ll, ll>; using namespace std; template<typename F, typename S> std::ostream &operator << (std::ostream &dest, const std::pair<F, S> &p) { dest << p.first << ' ' << p.second; return dest; } template<typename A, typename B> std::ostream &operator << (std::ostream &dest, const std::tuple<A, B> &t) { dest << std::get<0>(t) << ' ' << std::get<1>(t); return dest; } template<typename A, typename B, typename C> std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C> &t) { dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t); return dest; } template<typename A, typename B, typename C, typename D> std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C, D> &t) { dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << ' ' << std::get<3>(t); return dest; } template<typename T> std::ostream &operator << (std::ostream &dest, const std::vector<std::vector<T>> &v) { int sz = v.size(); if (!sz) return dest; for (int i = 0; i < sz; i++) { int m = v[i].size(); for (int j = 0; j < m; j++) dest << v[i][j] << (i != sz - 1 && j == m - 1 ? '\n' : ' '); } return dest; } template<typename T> std::ostream &operator << (std::ostream &dest, const std::vector<T> &v) { int sz = v.size(); if (!sz) return dest; for (int i = 0; i < sz - 1; i++) dest << v[i] << ' '; dest << v[sz - 1]; return dest; } template<typename T, size_t sz> std::ostream &operator << (std::ostream &dest, const std::array<T, sz> &v) { if (!sz) return dest; for (int i = 0; i < sz - 1; i++) dest << v[i] << ' '; dest << v[sz - 1]; return dest; } template<typename T> std::ostream &operator << (std::ostream &dest, const std::set<T> &v) { for (auto itr = v.begin(); itr != v.end();) { dest << *itr; itr++; if (itr != v.end()) dest << ' '; } return dest; } template<typename T, typename E> std::ostream &operator << (std::ostream &dest, const std::map<T, E> &v) { for (auto itr = v.begin(); itr != v.end(); ) { dest << '(' << itr->first << ", " << itr->second << ')'; itr++; if (itr != v.end()) dest << '\n'; } return dest; } template<typename T> vector<T> make_vec(size_t sz, T val) { return std::vector<T>(sz, val); } template<typename T, typename... Tail> auto make_vec(size_t sz, Tail ...tail) { return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...)); } template<typename T> vector<T> read_vec(size_t sz) { std::vector<T> v(sz); for (int i = 0; i < (int)sz; i++) std::cin >> v[i]; return v; } template<typename T, typename... Tail> auto read_vec(size_t sz, Tail ...tail) { auto v = std::vector<decltype(read_vec<T>(tail...))>(sz); for (int i = 0; i < (int)sz; i++) v[i] = read_vec<T>(tail...); return v; } // x / y以上の最小の整数 ll ceil_div(ll x, ll y) { assert(y > 0); return (x + (x > 0 ? y - 1 : 0)) / y; } // x / y以下の最大の整数 ll floor_div(ll x, ll y) { assert(y > 0); return (x + (x > 0 ? 0 : -y + 1)) / y; } void io_init() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); } #include <limits> struct hopcroft_karp { private: int N, M; std::vector<std::pair<int, int>> info; std::vector<std::vector<int>> G; std::vector<int> matchL, matchR; public: hopcroft_karp() : N(0), M(0) {} hopcroft_karp(int n, int m) : N(n), M(m), G(n), matchL(N, -1), matchR(M, -1) {} int add_edge(int s, int t) { assert(0 <= s && s < N); assert(0 <= t && t < M); int m = int(info.size()); info.push_back({s, t}); G[s].push_back(t); return m; } struct edge { int s, t; bool used; }; edge get_edge(int i) { int m = int(info.size()); assert(0 <= i && i < m); auto [s, t] = info[i]; return edge{s, t, matchL[s] == t}; } std::vector<edge> edges() { int M = int(info.size()); std::vector<edge> result; for (int i = 0; i < M; i++) result.push_back(get_edge(i)); return result; } int max_flow() { return max_flow(std::numeric_limits<int>::max()); } int max_flow(int flow_limit) { std::vector<int> level(N), iter(N), que(N); auto bfs = [&]() { std::fill(level.begin(), level.end(), -1); int l = 0, r = 0; for (int i = 0; i < N; i++) { if (matchL[i] == -1) { level[i] = 0; que[r++] = i; } } while (l < r) { int v = que[l++]; for (int t : G[v]) { int tt = matchR[t]; if (tt == -1 || level[tt] != -1) continue; level[tt] = level[v] + 1; que[r++] = tt; } } }; auto dfs = [&](auto self, int v) -> bool { int level_v = level[v]; for (int& i = iter[v]; i < int(G[v].size()); i++) { int t = G[v][i]; int tt = matchR[t]; if (tt == -1 || (level[tt] > level_v && self(self, tt))) { matchR[t] = v; matchL[v] = t; return true; } } return false; }; int flow = 0; while (flow < flow_limit) { bfs(); std::fill(iter.begin(), iter.end(), 0); bool ok = false; for (int i = 0; i < N && flow < flow_limit; i++) { if (matchL[i] != -1) continue; bool f = dfs(dfs, i); flow += f; ok |= f; } if (!ok) break; } return flow; } std::vector<int> pairL() const { return matchL; } std::vector<int> pairR() const { return matchR; } std::vector<std::pair<int, int>> pairs() const { std::vector<std::pair<int, int>> res; for (int i = 0; i < N; i++) { if (matchL[i] != -1) { res.push_back({i, matchL[i]}); } } return res; } // 点カバー (= max_flow) (max_flowを先に呼ぶ) // {0, i} : 左のi {1, i} := 右のi std::vector<std::pair<bool, int>> min_vertex_cover() { std::vector<bool> visitedL(N, false), visitedR(M, false); auto dfs = [&](auto self, int v) { visitedL[v] = true; if (matchL[v] != -1) return; for (int t : G[v]) { visitedR[t] = true; if (matchR[t] == -1 || visitedL[matchR[t]]) continue; self(self, matchR[t]); } }; for (int i = 0; i < N; i++) { if (matchL[i] == -1 && !visitedL[i]) { dfs(dfs, i); } } std::vector<std::pair<bool, int>> res; for (int i = 0; i < N; i++) { if (!visitedL[i]) res.push_back({0, i}); } for (int i = 0; i < M; i++) { if (visitedR[i]) res.push_back({1, i}); } return res; } // 最大独立集合 (= (N + M) - max_flow) (max_flowを先に呼ぶ) // {0, i} : 左のi {1, i} := 右のi std::vector<std::pair<bool, int>> max_independent_set() { // } }; int main() { io_init(); int H, W; std::cin >> H >> W; auto A = read_vec<int>(H, W); std::vector<std::pair<int, int>> R, C; for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { if (A[i][j] == 0) continue; R.push_back({i, A[i][j]}); C.push_back({j, A[i][j]}); } } sort(allof(R)); R.erase(unique(allof(R)), R.end()); sort(allof(C)); C.erase(unique(allof(C)), C.end()); hopcroft_karp G(R.size(), C.size()); for (int i = 0; i < H; i++) { for (int j = 0; j < W; j++) { if (A[i][j] == 0) continue; int idx1 = std::lower_bound(allof(R), std::pair<int, int>{i, A[i][j]}) - R.begin(); int idx2 = std::lower_bound(allof(C), std::pair<int, int>{j, A[i][j]}) - C.begin(); G.add_edge(idx1, idx2); } } int f = G.max_flow(); assert(f == G.min_vertex_cover().size()); std::cout << f << '\n'; }