#include #include #include #include #include #include #include #include struct DFSMatching { DFSMatching(int32_t n, int32_t m): n_(n), m_(m), graph_(n), rev_(m, -1), vis_(m, 0) {} void addEdge(int32_t u, int32_t v) { graph_[u].push_back(v); } bool find(int32_t v) { if (rev_[v] == -1) return true; vis_[v] = true; int32_t u = rev_[v]; for (auto w : graph_[u]) { if (!vis_[w] && find(w)) { rev_[w] = u; return true; } } return false; } // return the size of the maximum matching int32_t findMatching() { for (auto i = 0; i < n_; ++i) { std::fill(vis_.begin(), vis_.end(), 0); for (auto j : graph_[i]) { if (find(j)) { rev_[j] = i; break; } } } return m_ - std::count(rev_.begin(), rev_.end(), -1); } int32_t n_, m_; std::vector> graph_; std::vector rev_; std::vector vis_; }; int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); int32_t n, m; std::cin >> n >> m; std::vector> fixers(m); for (auto i = 0; i < n; ++i) { std::string s; std::cin >> s; for (auto j = 0; j < m; ++j) { if (s[j] == '1') { fixers[j].push_back(i); } } } std::vector usefulEng; usefulEng.reserve((m + 1) * (m + 1)); for (auto j = 0; j < m; ++j) { // TODO: shuffle? if (fixers[j].size() > m) { fixers[j].resize(m + 1); } for (auto eng : fixers[j]) { usefulEng.push_back(eng); } } std::sort(usefulEng.begin(), usefulEng.end()); usefulEng.erase(std::unique(usefulEng.begin(), usefulEng.end()), usefulEng.end()); for (auto j = 0; j < m; ++j) { for (auto& eng : fixers[j]) { eng = std::lower_bound(usefulEng.begin(), usefulEng.end(), eng) - usefulEng.begin(); } } auto hasMatch = [&](int32_t serviceMask, int32_t k) -> bool { DFSMatching match(k, usefulEng.size()); for (auto j = 0, idx = 0; j < m; ++j) { if ((serviceMask >> j & 1) == 0) continue; for (auto eng : fixers[j]) { match.addEdge(idx, eng); } idx++; } return match.findMatching() >= k; }; std::vector> serviceMasks(m + 1); for (auto i = 0; i < (1 << m); ++i) { auto k = __builtin_popcount(i); serviceMasks[k].push_back(i); } int ans = m; for (int k = 1; k <= m; k++) { bool valid = true; for (auto serviceMask : serviceMasks[k]) { if (!hasMatch(serviceMask, k)) { valid = false; break; } } if (!valid) { ans = k - 1; break; } } std::cout << ans << '\n'; return 0; }