POJ 1988(带权并查集)
POJ 1988
- 题目问的是包括x方块的堆 下面的 所有方块的个数,而不是方块x下面所有方块的个数,
- 将最下面的方块作为根节点(父亲节点设置时带方向)
- 一个数组记录此堆的数量,另一个数组记该点下面方块的个数
- find(x)时,更新所有点的下面方块个数,
- 询问点x的结果时,首先要find(x),使的结果为该堆的根节点下面的方块数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <iostream> using namespace std; const int maxn = 3e4+5; int tot[maxn],pre[maxn],down[maxn]; void init() { for (int i=1; i<maxn; i++) { tot[i] = 1; pre[i] = i; down[i] = 0; } } int find(int x) { if (x != pre[x]) { int lastx = pre[x]; pre[x] = find(pre[x]); down[x] += down[lastx]; } return pre[x]; } void merge(int a,int b) { int root_a = find(a); int root_b = find(b); if (root_a != root_b) { pre[root_a] = root_b; down[root_a] = tot[root_b]; tot[root_b] += tot[root_a]; } } int main() { freopen("a.txt","r",stdin); int p; cin >> p;
init();
char ch; int u,v; for (int k=0; k<p; k++) { cin >> ch; if (ch == 'M') { cin >> u >> v; merge(u,v); } else { cin >> u;
find(u); printf("%d\n",down[u]); } } return 0; }
|