zl程序教程

您现在的位置是:首页 >  其它

当前栏目

ZOJ3261并查集逆向处理

处理 逆向 查集
2023-09-11 14:14:00 时间
题意:
      给你一些点,还有一些边,每个点上都有一个权值,然后有一些询问,分为两种,
query a 询问与a直接或者间接想连的点中最大权值的是那个点,输出那个点,如果那个点的权值小于等于a的权值,那么就输出-1,还有另一种操作就是destroy a b意思是删除a b的关系。


思路:

      比较基础的并查集题目,看到删边,很容易想到逆向离线处理,先把最终的状态建立出来,然后对于询问逆向处理,正向是删边,那么逆向肯定是加边了,更新最优的话也是比较简单的并查集小变种(也就是平时说的带权并查集),一开始wa了好几次,原因是没有注意一点,就是最大值相等的要编号小的点,这个注意下,别的没啥,具体细节看代码。


#include<map>
#include<stdio.h>
#include<string.h>

#define N_node 10000 + 50
#define N_edge 20000 + 50
#define N_q 50000 + 50

using namespace std;

typedef struct
{
   int a ,b;
}EDGE;

typedef struct
{
   int key ,a ,b ,ans;
}QQ;

int mer[N_node] ,num[N_node];
int _max[N_node] ,maxid[N_node];
map<int ,map<int ,int> >mark;
EDGE E[N_edge];
QQ Q[N_q];

int finds(int x)
{
    x == mer[x] ? x : mer[x] = finds(mer[x]);
}

int main ()
{
    int n ,m ,q ,i;
    char str[10];
    int mk = 0;
    while(~scanf("%d" ,&n))
    {
        if(mk) printf("\n");
        mk = 1;
        for(i = 1 ;i <= n ;i ++)
        scanf("%d" ,&num[i]);
        scanf("%d" ,&m);
        for(i = 1 ;i <= m ;i ++)
        {
            scanf("%d %d" ,&E[i].a ,&E[i].b);
            E[i].a ++ ,E[i].b ++;
        }
        scanf("%d" ,&q);
        mark.clear();
        for(i = 1 ;i <= q ;i ++)
        {
            scanf("%s" ,str);
            if(str[0] == 'q')
            {
                scanf("%d" ,&Q[i].a);
                Q[i].key = 1;
                Q[i].a ++;
            }
            else
            {
                scanf("%d %d" ,&Q[i].a ,&Q[i].b) ,Q[i].key = 2;
                Q[i].a ++ ,Q[i].b ++;
                mark[Q[i].a][Q[i].b] = mark[Q[i].b][Q[i].a] = 1;
            }

        }
        for(i = 1 ;i <= n ;i ++)
        maxid[i] = mer[i] = i ,_max[i] = num[i];
        for(i = 1 ;i <= m ;i ++)
        {
            if(mark[E[i].a][E[i].b]) continue;
            int x = finds(E[i].a);
            int y = finds(E[i].b);
            if(x != y)
            {
                mer[x] = y;
                if(_max[y] < _max[x] || _max[y] == _max[x] && maxid[y] > maxid[x])
                {
                    _max[y] = _max[x];
                    maxid[y] = maxid[x];
                }
            }
        }
        for(i = q ;i >= 1 ;i --)
        {
            if(Q[i].key == 1)
            {
                int x = finds(Q[i].a);
                if(_max[x] > num[Q[i].a]) Q[i].ans = maxid[x] - 1;
                else Q[i].ans = -1;
            }
            else
            {
                int x = finds(Q[i].a);
                int y = finds(Q[i].b);
                if(x != y)
                {
                    mer[x] = y;
                    if(_max[y] < _max[x] || _max[y] == _max[x] && maxid[y] > maxid[x])
                    {
                        _max[y] = _max[x];
                        maxid[y] = maxid[x];
                    }
                }
            }
        }
        for(i = 1 ;i <= q ;i ++)
        if(Q[i].key == 1) printf("%d\n" ,Q[i].ans);

    }
    return 0;
}