• 数据结构学习笔记 - 带权并查集(食物链题解)


    前言

    并查集的概念:将编号分别为 1~n 的 n 个对象划分为不相交集合,在每个集合中,选择其中某个元素代表所在集合。

    并查集的基本应用是集合问题。在加上权值之后,利用并查集的合并优化和路径压缩,可以对权值所代表的具体应用进行高效的操作。

    查询的优化(路径压缩)

    普通的查询函数是查询元素 i 所属的集需要搜索路径到根节点并返回,这样显然会浪费很长时间。如果我们在返回时顺便把 i 所属的集改为根节点,那么下次再搜的时候可以直接 O(1) 得到结果。

    1. int find(int x){
    2. if(x == fa[x]) return fa[x];
    3. return fa[x] = find(fa[x]);
    4. }

    带权并查集

    除了并查集的基本应用 - 处理集合问题。

    定义一个权值数组 d[] 把节点 i 到父节点的权值记为 d[i]

    带权值的路径压缩

    原来的权值 d[],经过压缩之后,更新为 d[]',例如 d[1]' = d[1] + [2] + d[3](也可以是乘、异或等)

    1. int find(int x){
    2. if(x != fa[x]){
    3. int t = fa[x]; // 记录父节点
    4. fa[x] = find(fa[x]); // 路径压缩,递归最后返回的是根节点
    5. d[x] = (d[x] + d[t]) % 3;; // 权值更新为 x 到根节点的权值
    6. }
    7. return fa[x];
    8. }

    原来的 d[x] 是点 x 到它的父节点的权值,经过路径压缩后,x 直接指向根节点,d[x] 也更新为 x 到根节点的权值。这是通过递归实现的。

    代码中先用 t 记录 x 的原父节点;在递归过程中,最后返回的是根节点;最后将当前节点的权值加上原父节点的权值(注意:经过递归,此时父节点也直接指向根节点,父节点的权值也已经更新为父节点直接到根节点的权值了),就得到当前节点到根节点的权值。

    带权值的合并

    在合并操作中,把点 x 与点 y 合并,就是把点 x 的根节点 fx 合并到点 y 的根节点 fy。在 fx 和 fy 之间增加权值,这个权值要符合题目的要求。

    食物链题解

    解题思路

    本题有两种解法,一个是带权并查集,另一个是扩展并查集。

    带权并查集

    题目中的权值关系是指两个动物在食物链上的相对关系。

    d(A->B) 表示 A 和 B 的关系,d(A->B) = 0 表示同类,d(A->B) = 1 表示 A 吃 B,d(A->B) = 2 表示 A 被 B 吃。

    d(A->B) = 1,d(B->C) = 1,求 d(A->C)。因为 A 吃 B,B 吃 C,那么 C 应该吃 A,得 d(A->C) = 2

    d(A->B) = 2,d(B->C) = 2,求 d(A->C)。因为 B 吃 A,C 吃 B,那么 A 应该吃 C,得 d(A->C) = 1

    d(A->B) = 0,d(B->C) = 1,求 d(A->C)。因为 A B 同类,B 吃 C,那么 A 吃 C,得 d(A->C) = 1

    d(A->C) = (d(A->B) + d(B->C)) % 3

    1. /* 三倍并查集
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int maxn = 3000100;
    9. int n, m;
    10. int ans;
    11. int fa[maxn];
    12. int a[maxn];
    13. int find(int x){
    14. if(x == fa[x]) return fa[x];
    15. return fa[x] = find(fa[x]);
    16. }
    17. int main(){
    18. cin >> n >> m;
    19. int z, x, y;
    20. for(int i = 1; i <= n * 3; i++) fa[i] = i;
    21. for(int i = 1; i <= m; i++){
    22. cin >> z >> x >> y;
    23. if(x > n || y > n){
    24. ans++;
    25. continue;
    26. }
    27. if(z == 1){
    28. if(find(x) == find(y + n) || find(x + n) == find(y)){
    29. ans++;
    30. continue;
    31. }
    32. else{
    33. fa[find(x)] = find(y);
    34. fa[find(x + n)] = find(y + n);
    35. fa[find(x + 2 * n)] = find(y + 2 * n);
    36. }
    37. }
    38. else{
    39. if(find(x) == find(y) || find(x) == find(y + n)){
    40. ans++;
    41. continue;
    42. }
    43. else{
    44. fa[find(x)] = find(y + 2 * n);
    45. fa[find(x + n)] = find(y);
    46. fa[find(x + 2 * n)] = find(y + n);
    47. }
    48. }
    49. }
    50. cout << ans << '\n';
    51. system("pause");
    52. }
    53. */
    54. #include
    55. using namespace std;
    56. const int maxn = 1001000;
    57. int n, m;
    58. int ans;
    59. int fa[maxn];
    60. int d[maxn];
    61. int find(int x){
    62. if(x != fa[x]){
    63. int t = fa[x];
    64. fa[x] = find(fa[x]);
    65. d[x] = (d[x] + d[t]) % 3;;
    66. }
    67. return fa[x];
    68. }
    69. void merge(int x, int y, int type){
    70. int fax = find(x);
    71. int fay = find(y);
    72. if(fax == fay){
    73. if((type - 1) != (d[x] - d[y] + 3) % 3) ans++;
    74. return;
    75. }
    76. else{
    77. fa[fax] = fay;
    78. d[fax] = (d[y] - d[x] + type - 1) % 3;
    79. }
    80. }
    81. int main(){
    82. cin >> n >> m;
    83. int z, x, y;
    84. for(int i = 1; i <= n; i++) fa[i] = i;
    85. for(int i = 1; i <= m; i++){
    86. cin >> z >> x >> y;
    87. if(x > n || y > n || (z == 2 && x == y)){
    88. ans++;
    89. continue;
    90. }
    91. else merge(x, y, z);
    92. }
    93. cout << ans << '\n';
    94. system("pause");
    95. }
  • 相关阅读:
    css h5 端弹窗时禁止底部页面滚动
    vue课程79 介绍并安装vue-cli
    计算机自顶向下
    VScode使用M5stack-c plus基于arduino-环境搭建
    B. Suffix Operations
    海康相机SDK二次开发的一些报错和解决办法
    拿到一个新的SpringBoot+Maven多模块项目,怎么跑起来
    我是如何组织 Go 代码的(目录结构 依赖注入 wire)
    软件开发工程师笔试记录--关键路径,浮点数计算,地址变换,中断向量,I/O接口,海明码
    【目标检测】YOLOv5分离检测和识别
  • 原文地址:https://blog.csdn.net/haobowen/article/details/127819377