#include typedef long long ll; typedef long double ld; using namespace std; #define rep(i, a, n) for (int i = (a); i < (n); i++) #define per(i, a, n) for (int i = (n) - 1; i >= (a); i--) ll MOD=1000000007; class MaximumMatching { vector> left_to_right, right_to_left; public: void add_edge(int left, int right); int maximum_matching_size() { return maximum_matching().size(); } vector> maximum_matching(); pair, vector> minimum_vertex_cover(); }; void MaximumMatching::add_edge(int left, int right) { if (int(left_to_right.size()) <= left) left_to_right.resize(left + 1); if (int(right_to_left.size()) <= right) right_to_left.resize(right + 1); left_to_right[left].push_back(right); right_to_left[right].push_back(left); } vector> MaximumMatching::maximum_matching() { int L = left_to_right.size(), R = right_to_left.size(); vector match(L, -1); for (int r=0;r < R; r++) { bool found = false; vector from(L, -1); queue Q; for (int x : right_to_left[r]) { Q.push(x); from[x] = x; } while (!Q.empty() && !found) { int l = Q.front(); Q.pop(); if (match[l] == -1) { found = true; while (from[l]!=l) { match[l] = match[from[l]]; l = from[l]; } match[l] = r; } else { for (int x : right_to_left[match[l]]) if (from[x] == -1) { Q.push(x); from[x] = l;} } } } vector> result; for (int i=0; i,vector> MaximumMatching::minimum_vertex_cover() { int L = left_to_right.size(), R = right_to_left.size(); vector> matching = maximum_matching(); vector match(L, -1); vectormatched(R, false); for (auto m : matching) { match[m.first] = m.second; matched[m.second]=true; } vector visited(L, false); queue Q; for (int r=0; r left_cover, right_cover; for (int l = 0; l> n){ int i; unordered_map m; MaximumMatching match; int a,b; vector > x; for(i=0;i> a >> b; a++; b++; x.push_back({a,b}); m[a*MOD+b]=i+1; } for(i=0;i, vector > p=match.minimum_vertex_cover(); cout << n-p.first.size()-p.second.size() << endl; } return 0; }