#include using namespace std; #define int long long #define REP(i,m,n) for(int i=(m);i<(n);i++) #define rep(i,n) REP(i,0,n) #define pb push_back #define all(a) a.begin(),a.end() #define rall(c) (c).rbegin(),(c).rend() #define mp make_pair #define endl '\n' #define vec vector #define mat vector > #define fi first #define se second #define double long double typedef long long ll; typedef unsigned long long ull; typedef pair pll; //typedef long double ld; typedef complex Complex; const ll INF=1e9+7; const ll inf=INF*INF; const ll mod=998244353; const ll MAX=140010; //Union-Find木 struct UnionFind { vector< int > data; UnionFind() = default; explicit UnionFind(size_t sz) : data(sz, -1) {} bool unite(int x, int y) { x = find(x), y = find(y); if(x == y) return false; if(data[x] > data[y]) swap(x, y); data[x] += data[y]; data[y] = x; return true; } int find(int k) { if(data[k] < 0) return (k); return data[k] = find(data[k]); } int size(int k) { return -data[find(k)]; } bool same(int x, int y) { return find(x) == find(y); } }; signed main(){ ll n,m;cin>>n>>m; UnionFind uf(m); vector >box(n); rep(i,n){ ll b,c;cin>>b>>c; c--; b--; box[c].pb(b); } rep(i,n){ REP(j,1,box[i].size()){ uf.unite(box[i][j],box[i][j-1]); } } vectorused(m); ll cnt=0; rep(i,m){ if(used[uf.find(i)])continue; used[uf.find(i)]=1; cnt++; } cout<