• 可撤销并查集学习笔记


    可撤销并查集——个人理解与学习笔记

      网上有很多博客都是只放了一个代码,然后让读者自己解读代码,这里我写点自己的理解。

      撤销的是什么?撤销的是操作。

      如果我们让u和v链接,那么实际上是u和v的祖先是不同的,那么也就是fu = fid(u), fv = fid(v),如果fu!=fv,那么我们就将这样的操作放入,并且考虑到下次需要撤销,所以需要存储上一次的信息:

    存储信息(假设我们让fa[fu] = fv):

    1.记录fa[fu]的原来的节点,存{fa[fu](指针), fa[fu](对应的值)};

    2.如果改变了深度,也就是deep[fv]的值改变了,那么就需要考虑存储{deep[fv](指针), deep[fv](值)}。

    于是,有的时候需要撤销两次,有时候需要撤销一次。

    所以,根据以上的信息,我们可以先写出寻找祖先的函数:

    int fid(int x) { return x == fa[x] ? x : fid(fa[x]); }

    然后是合并函数

    void Merge(int x, int y)
    {
        x = fid(x); y = fid(y);
        if(x == y) return;
        Stap[++Stop] = 1;
        if(deep[x] > deep[y]) swap(x, y);
        stk.push(MP(fa + x, fa[x]));
        fa[x] = y;
        if(deep[x] == deep[y])
        {
            Stap[Stop]++;
            stk.push(MP(deep + y, deep[y]));
            deep[y]++;
        }
    }

    然后是撤销函数

    void Undo()
    {
        *stk.top().first = stk.top().second;
        stk.pop();
    }

    最后,我再放一个完整的

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <string>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <limits>
     8 #include <vector>
     9 #include <stack>
    10 #include <queue>
    11 #include <set>
    12 #include <map>
    13 #include <bitset>
    14 #include <unordered_map>
    15 #include <unordered_set>
    16 #define lowbit(x) ( x&(-x) )
    17 #define pi 3.141592653589793
    18 #define e 2.718281828459045
    19 #define INF 0x3f3f3f3f
    20 #define HalF (l + r)>>1
    21 #define lsn rt<<1
    22 #define rsn rt<<1|1
    23 #define Lson lsn, l, mid
    24 #define Rson rsn, mid+1, r
    25 #define QL Lson, ql, qr
    26 #define QR Rson, ql, qr
    27 #define myself rt, l, r
    28 #define pii pair<int, int>
    29 #define MP(a, b) make_pair(a, b)
    30 using namespace std;
    31 typedef unsigned long long ull;
    32 typedef unsigned int uit;
    33 typedef long long ll;
    34 const int maxN = 1e5 + 7;
    35 stack<pair<int * , int>> stk;
    36 int fa[maxN], deep[maxN];
    37 int N, M;
    38 void init()
    39 {
    40     for(int i = 1; i <= N; i++) { fa[i] = i; deep[i] = 0; }
    41 }
    42 int fid(int x) { return x == fa[x] ? x : fid(fa[x]); }
    43 int Stap[maxN], Stop;
    44 void Merge(int x, int y)
    45 {
    46     x = fid(x); y = fid(y);
    47     if(x == y) return;
    48     Stap[++Stop] = 1;
    49     if(deep[x] > deep[y]) swap(x, y);
    50     stk.push(MP(fa + x, fa[x]));
    51     fa[x] = y;
    52     if(deep[x] == deep[y])
    53     {
    54         Stap[Stop]++;
    55         stk.push(MP(deep + y, deep[y]));
    56         deep[y]++;
    57     }
    58 }
    59 void Undo()
    60 {
    61     *stk.top().first = stk.top().second;
    62     stk.pop();
    63 }
    64 int main()
    65 {
    66     scanf("%d%d", &N, &M);
    67     init();
    68     Stop = 0;
    69     for(int i = 1, op, u, v; i <= M; i++)
    70     {
    71         scanf("%d", &op);
    72         if(op == 1)
    73         {
    74             scanf("%d%d", &u, &v);
    75             Merge(u, v);
    76         }
    77         else if(op == 2)
    78         {
    79             while(Stap[Stop]--) Undo();
    80             Stop--;
    81         }
    82         else
    83         {
    84             scanf("%d%d", &u, &v);
    85             u = fid(u); v = fid(v);
    86             printf("%d
    ", u == v);
    87         }
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    Codeforces Round #720 (Div. 2) B. Nastia and a Good Array(被坑好几次)1300
    B. Lord of the Values 思维数学建构 附加 英文翻译
    几个i的幂的累加公式1^2+2^2+3^2 2~5
    Codeforces Round #721 (Div. 2)A. And Then There Were K(位运算,二进制) B1. Palindrome Game (easy version)(博弈论)
    洛谷 P2392 kkksc03考前临时抱佛脚, dp / 深搜
    Codeforces Round #719 (Div. 3) C. Not Adjacent Matrix
    Educational Codeforces Round 108 (Div. 2), C map套vector存储
    Day39---->MySQL系列
    Day38——>MySQL
    Day37
  • 原文地址:https://www.cnblogs.com/WuliWuliiii/p/13936489.html
Copyright © 2020-2023  润新知