#include<bits/stdc++.h> #include<atcoder/all> #define rep(i,n) for(int i=0;i<n;i++) using namespace std; // Coodinate Compression // https://youtu.be/fR3W5IcBGLQ?t=8550 template<typename T=int> struct CC { bool initialized; vector<T> xs; CC(): initialized(false) {} void add(T x) { xs.push_back(x);} void init() { sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(),xs.end()),xs.end()); initialized = true; } int operator()(T x) { if (!initialized) init(); return upper_bound(xs.begin(), xs.end(), x) - xs.begin() - 1; } T operator[](int i) { if (!initialized) init(); return xs[i]; } int size() { if (!initialized) init(); return xs.size(); } }; int main(){ int N; long long M; cin >> N >> M; CC<long long> cc; vector<pair<long long, long long>> target; rep(i, N){ long long l, r; cin >> l >> r; target.emplace_back(l, r); cc.add(l); cc.add(r); } int K = cc.size(); atcoder::mf_graph<int> graph(N + K + 2); int sv = N + K; int tv = N + K + 1; rep(i, N) graph.add_edge(sv, i, 1); rep(i, N){ auto [l, r] = target[i]; graph.add_edge(i, N + cc(l), 1); graph.add_edge(i, N + cc(r), 1); } rep(x, K) graph.add_edge(N + x, tv, 1); int ans = graph.flow(sv, tv); cout << ans << "\n"; return 0; }