zoukankan      html  css  js  c++  java
  • ZOJ3261并查集逆向处理

    题意:
          给你一些点,还有一些边,每个点上都有一个权值,然后有一些询问,分为两种,
    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("
    ");
            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
    " ,Q[i].ans);
    
        }
        return 0;
    }
    


  • 相关阅读:
    sql server 纵横表的转换
    url参数的编码解码Demo
    SqlServer 列的增加和删除
    asp.net下ajax.ajaxMethod使用方法(转)
    js中document.all 的用法
    cookie跨域,跨目录访问及单点登录。
    错误记录:html隐藏域的值存字符串时出错
    .NET下用C#实现邮箱激活功能
    js与C#服务端 json数据交互
    sqlserver数据可空插入报错
  • 原文地址:https://www.cnblogs.com/csnd/p/12062433.html
Copyright © 2011-2022 走看看