struct DSU {
vector<int> parent, rank;
explicit DSU(int n) : parent(n), rank(n, 0) {
for (int i = 0; i < n; ++i) parent[i] = i;
}
int find(int v) {
if (v == parent[v]) return v;
return parent[v] = find(parent[v]);
}
void unite(int a, int b) {
a = find(a);
b = find(b);
if (a == b) return;
if (rank[a] < rank[b]) swap(a, b);
parent[b] = a;
if (rank[a] == rank[b]) ++rank[a];
}
};
struct DSU {
vector<int> parent, rank;
explicit DSU(int n) : parent(n), rank(n, 0) {
for (int i = 0; i < n; ++i) parent[i] = i;
}
int find(int v) {
if (v == parent[v]) return v;
return parent[v] = find(parent[v]);
}
void unite(int a, int b) {
a = find(a);
b = find(b);
if (a == b) return;
if (rank[a] < rank[b]) swap(a, b);
parent[b] = a;
if (rank[a] == rank[b]) ++rank[a];
}
};