Problem Description
John are playing with blocks. There are N blocks (1 <= N <= 30000) numbered 1...N。Initially, there are N piles, and each pile contains one block. Then John do some operations P times (1 <= P <= 1000000). There are two kinds of operation:
M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X
You are request to find out the output for each C operation.
M X Y : Put the whole pile containing block X up to the pile containing Y. If X and Y are in the same pile, just ignore this command.
C X : Count the number of blocks under block X
You are request to find out the output for each C operation.
Input
The first line contains integer P. Then P lines follow, each of which contain an operation describe above.
Output
Output the count for each C operations in one line.
Sample Input
6 M 1 6 C 1 M 2 4 M 2 6 C 3 C 4
Sample Output
1 02
求一个点下面有多少点,并查集,用最下面的点作为集合的代表。
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; const int maxn = 30005; int T, a, b, cnt[maxn], und[maxn], fa[maxn]; char c; int find(int x) { if (x != fa[x]){ int t = find(fa[x]); und[x] += und[fa[x]]; fa[x] = t; } return fa[x]; } void merge(int x, int y) { int fx = find(x), fy = find(y); if (fx == fy) return; fa[fx] = fy; und[fx] += cnt[fy]; cnt[fy] += cnt[fx]; } int main(){ scanf("%d", &T); for (int i = 0; i < maxn; i++) fa[i] = i, cnt[i] = 1; while (T--) { cin >> c; switch (c){ case 'C':scanf("%d", &a); find(a); printf("%d\n", und[a]); break; case 'M':scanf("%d%d", &a, &b); merge(a, b); break; } } return 0; }