poj 1988 多校联赛 带权并查集
这个题的意思是初始给你N个砖块, 维护两个操作, M a, b表示将含有a的堆放到b堆得上面(a和b在同一堆得话那么就忽略此操作, 有种并查集的感觉), C a查询a下面有几个砖块, 其实我们可以使用带权的并查集来维护这个题, 增加两个变量under[i]表示i下面有几个装快, cnt[i]表示以i为底的堆有几个砖块, 然后我们就可以在并查集Find函数回溯的时候就可以更新under数组。。 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 30000 + 100; int par[maxn]; int cnt[maxn], under[maxn]; void init(int n) { for(int i=1; i<=n; i++) { par[i] = i; cnt[i] = 1; under[i] = 0; } } int Find(int x) { if(x == par[x]) return x; else { int t = Find(par[x]); under[x] += under[par[x]]; //加过之后 路径压缩 return par[x]=t; } } void Union(int x, int y) { x = Find(x); y = Find(y); if(x != y) //x摞在y上 { under[x] = cnt[y]; cnt[y] += cnt[x]; par[x] = y; } } char s[10]; int main() { int N; while(scanf("%d", &N) != EOF) { init(30000); for(int i=0; i<N; i++) { scanf("%s", s); if(s[0] == 'M') { int a, b; scanf("%d%d", &a, &b); Union(a, b); } else { int a; scanf("%d", &a); Find(a); printf("%d\n", under[a]); } } } return 0; }