POJ-1988-Cube Stacking
零、经验总结
- 家族人数
- 到根节点距离
- 利用人数更新到根节点距离
一、题目大意
有个箱子,初始时每个箱子单独为一列;
接下来有行输入,, , 或者 , ;
对于,,:表示将箱子所在的一列箱子搬到所在的一列箱子上;
对于,:表示查询箱子下面有多少个箱子;
二、解析
本题在并查集的基础上,要求输出当前节点的子节点数量。
其实可以转化为带权并查集的问题,求出当前节点的祖先的总子孙数量,减去当前节点到祖先的距离再减一即可。
代表到自己的祖先的距离(也就是上面有多少节点)
代表以为根节点的子孙数量(只对根节点有效,因为在合并时,非根节点的值将不再被更新)
代表的祖先
三、实现代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 30010;
int T; // 操作数量
int p[N]; // 并查集数组
int sz[N]; // 每个家族中节点数量
int d[N]; // 每个节点到根节点的距离
char op; // 操作符
// 带权并查集模板
int find(int x) {
// 点权的理解:每个点到根的距离
if (p[x] == x) return x; // 自己是老大,返回自己
int px = find(p[x]); // 通过自己父亲找老大
d[x] += d[p[x]]; // 点权在路径压缩过程中,需要加上父亲的点权
return p[x] = px; // 路径压缩
}
// 合并并查集
void join(int x, int y) {
int px = find(x), py = find(y);
if (px != py) {
p[py] = px; // px所在的子树放到py所在子树之上
// 下面这句话是本题相关的修改,重要!!!
d[py] = sz[px]; // py到px的距离就是px所在子树的结点个数[这个转换太漂亮了]
sz[px] += sz[py]; // px所在子树结点个数要加上py这一棵树子树
}
}
int main() {
// p父结点 sz当前节点子树大小 dis当前节点到根结点距离
for (int i = 1; i <= N - 10; i++) p[i] = i, sz[i] = 1;
cin >> T;
while (T--) {
cin >> op;
int x, y;
if (op == 'M') { // 合并
cin >> x >> y;
join(x, y);
} else {
cin >> x;
// 查找某一个点x下边有几个点时,只用求出x根结点所在子树的结点个数-x到根结点的距离-1
printf("%d\n", sz[find(x)] - d[x] - 1);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2019-04-11 什么是动态规划?动态规划的意义是什么?