• 可撤销并查集学习笔记


    可撤销并查集用启发式合并来优化。

    用一个栈来记录合并的操作,按照逆序恢复到原来的状态。

    记录一个撤销栈,元素为有序对 <int* pElem,int nValue>,如果撤销这个步骤则令 *pElem=nValue 即可。那么在启发式合并的时候,每次修改了什么就记录什么,撤销的时候删除即可。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    
    struct dsu 
    {
        int fa[N],rank[N];
        stack<pair<int*,int>> sta;
        void init(int n)
        {
            for(int i=1;i<=n;i++) 
            {
                fa[i]=i;
                rank[i]=1;
            }
        }
        int find(int p)
        {
            return fa[p]==p ? p : find(fa[p]);
        }
        void merge(int p,int q)
        {
            p=find(p);
            q=find(q);
            if(p!=q)
            {
                if(rank[p]>rank[q]) swap(p,q);
                sta.push({fa+p,fa[p]});
                fa[p]=q;
                if(rank[p]==rank[q])
                {
                    sta.push({rank+q,rank[q]});
                    ++rank[q];
                }
                else
                {
                    sta.push({NULL,0});
                }
            }
        }
        void _undo()
        {
            if(sta.size()==0) return;
            if(sta.top().first!=NULL)
            {
                *sta.top().first=sta.top().second;
            }
            sta.pop();
        }
        void undo()
        {
            _undo();
            _undo();
        }
        void print(int n)
        {
            cout<<" FA[] = ";
            for(int i=1;i<=n;i++)
            {
                cout<<fa[i]<<" ";
            }
            cout<<endl;
        }
    } dsu;
    
    signed main()
    {
        int n;
        cin>>n;
        dsu.init(n);
        while(true)
        {
            string op;
            int t1,t2;
            cin>>op;
            if(op=="merge")
            {
                cin>>t1>>t2;
                dsu.merge(t1,t2);
            }
            if(op=="undo")
            {
                dsu.undo();
            }
            dsu.print(n);
        }
    }
    
  • 相关阅读:
    函数嵌套
    函数对象
    可变长参数
    函数的参数
    函数的调用
    函数的返回值
    定义函数的三种形式
    函数的定义
    SQLAlchemy
    Flask总结完整版
  • 原文地址:https://www.cnblogs.com/mollnn/p/13768446.html
Copyright © 2020-2023  润新知