POJ--1988 Cube Stacking

题目链接: Cube Stacking

题意

M a b 代表把包含第一个数字的栈放到包含第6个数字上面的栈的上方。 开始的时候栈从1 - N标号,每个栈里的数字是它的标号。如果输入C a 代表让你输出 a 数字下方的数字有多少个。

思路

想了挺长时间,发现大部分题解还是想的有些麻烦。这也是道经典的带权并查集。under【i】代表第i 个数字下方有多少个数字,因此最终的答案就是under数组. 我们一般来说应用并查集的val【】数组记录的是此节点到根节点的距离,此题也是一样的,sum【i】代表 i 节点下的节点有多少个。 因此当我们执行combine操作的时候,under[fa] = sum[fb] 就代表 fa 节点的下方的数字的个数有 sum[fb]个。 这道题只不过是多了个sum[]数组,用并查集挺巧妙的。

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
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int sum[100001],f[100001],under[100001];
int Find(int x)
{
if(x != f[x])
{
int t = f[x];
f[x] = Find(f[x]);
under[x] += under[t];
}
return f[x];
}
void combine(int a,int b)
{
int fa = Find(a);
int fb = Find(b);
f[fa] = fb;
under[fa] = sum[fb];
sum[fb] += sum[fa];
}
int main()
{
int n,a,b;
string s;
cin >> n;
for(int i = 1; i <= n; ++i)
{
f[i] = i;
under[i] = 0;
sum[i] = 1;
}
for(int i = 1; i <= n; ++i)
{
cin >> s ;
if(s[0] == 'M')
{
cin >> a >> b;
combine(a,b);
}
else{
cin >> a;
int fa = Find(a);
cout << under[a] << endl;
}
}
}