WuliWuliiii
凤兮凤兮归故乡 遨游四海求其凰

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

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

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

  如果我们让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\n", u == v);
87         }
88     }
89     return 0;
90 }

 

posted on 2020-11-06 13:46  唔哩Wulili  阅读(116)  评论(0编辑  收藏  举报