• 并查集撤消操作


     https://www.cnblogs.com/y2823774827y/p/11600426.html

    int parent[maxn],siz[maxn];    //按秩合并用siz,siz小的连向siz大的 
    vector<pii> tmp;    //记录上次合并用到的节点 
    
    int find(int p)    //递归找根节点,注意没有路径压缩 
    {
    	if( p == parent[p] ) return p;
    	return find(parent[p]);
    }
    
    void done(pii v)  //合并两个点 
    {
    	int x = find(v.fi),y = find(v.se);
    	if( x == y )
    	{
    		tmp.push_back(mp(-1,-1));   //已经在同一集合中,不用再连了 
    		continue;
    	}
    	if( siz[x] > siz[y] )
    	    swap(x,y);  //一定是小的连向大的  
    	tmp.push_back(mp(x,y));    //把信息存入栈中 
    	parent[x] = y;             //合并一下 
    	siz[y] += siz[x];
    }
    
    void undone()    //反悔操作 
    {
    	pii z = tmp.back();   //取出栈顶元素 
    	tmp.pop_back();
    	if( z.fi == -1 )
    	    continue;   //那时候没有操作,那么也不需要回退 
    	parent[z.fi] = z.fi;         
    	//直接回退,做了啥就别做啥 
    	siz[z.se] -= siz[z.fi];
    }
    

      

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    typedef pair<int, int> PII;
    
    struct node{
        int x, y, z;
    }e[500010];
    
    struct query{
        int x, y, id;
        friend bool operator < (const query &a, const query &b){
            return a.id<b.id;
        }
    };
    
    int father[500010], ret[500010], n, m, qu;
    stack<PII > s;
    vector<query> v[500010];
    vector<PII > g[500010];
    
    int fd(int x){
        if(father[x]<0){
            return x;
        }
        else{
            return fd(father[x]);
        }
    }
    
    void work(int x, int y)
    {
        int fx=fd(x), fy=fd(y);
        if(fx==fy){
            return ;
        }
        if(father[fx]<=father[fy])
    	{
            father[fx]+=father[fy];
            father[fy]=fx;
    
        }
        else
    	{
            father[fy]+=father[fx];
            father[fx]=y;
        }
    }
    
    void solve(int cnt, int x, int y)
    {
    
        while(!s.empty()){
            s.pop();
        }
        for (int i=x; i<=y; ++i)
    	{
            int fx=fd(v[cnt][i].x), fy=fd(v[cnt][i].y);
    
            if(fx==fy){//如果有一条边添加不进去就不可以
                ret[v[cnt][i].id]=1;
            }
            else if(father[fx]<=father[fy]){
    
                s.push(make_pair(fy, father[fy]));
                father[fy]=fx;
            }
            else{
    
                s.push(make_pair(fx, father[fx]));
                father[fx]=fy;
            }
        }
        while(!s.empty())
    	{
            father[s.top().first] = s.top().second;
            s.pop();
        }
    }
    
    int main(){
    
        memset(father, -1, sizeof(father));
    
        scanf("%d%d", &n, &m);
        for(int i=1; i<=m; i++){
            scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].z);
            g[e[i].z].push_back(make_pair(e[i].x, e[i].y));
    		//按权值 保存原始边
        }
        scanf("%d", &qu);
        for(int i=1; i<=qu; i++)
    	{
            int opnum;
            scanf("%d", &opnum);
            for(int j=1; j<=opnum; j++)
    		{
                int x; 
    			scanf("%d", &x);
                v[e[x].z].push_back({e[x].x, e[x].y, i});
    			//按权值 保存所有的查询的边
            }
        }
    
        for(int i=1; i<=500000; i++)
    	{
            sort(v[i].begin(), v[i].end());
        }
    
        for(int i=1; i<=500000; i++)
    	{
            for(int j=0; j<g[i-1].size(); j++)
    		{//把权值<i的全部添加进去。形成的每个连通块包含的点集是一样的
                work(g[i-1][j].first, g[i-1][j].second);
            }
    
            int sz=v[i].size();
            if(sz==0)
    		{
                continue;
            }
            int now=0;
            while(now<sz)
    		{
                int j=now;
                while(j+1<sz&&v[i][j+1].id==v[i][j].id){
    			//找到把属于同一个询问的所有的边区间
                    j++;
                }
                solve(i, now, j);//判断这个区间
                now=j+1;
            }
        }
    
        for(int i=1; i<=qu; i++)
    	{
            printf("%s
    ", ret[i]?"NO":"YES");
        }
    
        return 0;
    }
    
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
     
    const int MAXN = 5e5 + 5;
     
    struct edge {
        int from, to, dist;
    };
     
    int n, m, q, cnt;
    int fa_1[MAXN], fa_2[MAXN], kase[MAXN];
    bool wa[MAXN];
    edge e[MAXN];
    vector<int> gra[MAXN];
    vector<pair<int, int> > qr[MAXN];
     
    int findfather_1(int x)
    {
        return (fa_1[x] == x ? x : fa_1[x] = findfather_1(fa_1[x]));
    }
     
    int findfather_2(int x)
    {
        if (kase[x] != cnt) 
    	   {
    	        kase[x] = cnt; 
    			fa_2[x] = findfather_1(x);
    	   }
        return (x == fa_2[x] ? x : fa_2[x] = findfather_2(fa_2[x]));
    }
     
    int main()
    {
        scanf("%d %d", &n, &m);
        int a, b, c, mx = 0;
        for (int i = 1; i <= m; i++) {
            scanf("%d %d %d", &a, &b, &c);
            e[i].from = a;
            e[i].to = b;
            e[i].dist = c;
            gra[c].push_back(i);
            mx = max(mx, c);
        }
        int k, x;
        scanf("%d", &q);
        for (int i = 1; i <= q; i++) 
    	{
            scanf("%d", &k);
            for (int j = 1; j <= k; j++) 
    		{
                scanf("%d", &x);
                qr[e[x].dist].push_back(make_pair(i, x));
            }
        }
        memset(wa, false, sizeof(wa));
        memset(kase, 0, sizeof(kase));
        for (int i = 1; i <= n; i++) fa_1[i] = i;
        cnt = 0;
        for (int i = 1; i <= mx; i++) 
    	{
            sort(qr[i].begin(), qr[i].end());
            for (int j = 0; j < qr[i].size(); j++) 
    		{
                if (j == 0 || qr[i][j].first != qr[i][j - 1].first) 
    			    cnt++;
                int x = findfather_2(e[qr[i][j].second].from);
                int y = findfather_2(e[qr[i][j].second].to);
                if (x == y) wa[qr[i][j].first] = true;
                fa_2[y] = x;
            }
            for (int j = 0; j < gra[i].size(); j++) {
                int x = findfather_1(e[gra[i][j]].from);
                int y = findfather_1(e[gra[i][j]].to);
                fa_1[y] = x;
            }
        }
        for (int i = 1; i <= q; i++)
            printf(!wa[i] ? "YES
    " : "NO
    ");
        return 0;
    }
    //https://blog.csdn.net/Shili_Xu/article/details/78726516
    

      

  • 相关阅读:
    Docker 容器默认root账号运行,很不安全!
    Prometheus阅读目录
    linux修改SSH远程登录端口 服务器安全篇
    linux 部署出现Fatal error: Class 'DOMDocument' not found。
    mysql开启远程访问权限
    linux 重置mysql 密码
    推送(极光推送)
    linux 搭建SVN
    C语言词频统计设计
    读《构建之法》有感
  • 原文地址:https://www.cnblogs.com/cutemush/p/14665081.html
Copyright © 2020-2023  润新知