zoukankan      html  css  js  c++  java
  • BZOJ 2594 水管局长数据加强版(动态树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2594

    题意:给出一个无向图,边有权值。定义一条路径的长度为该路径所有边的最大值。两种操作:(1)询问u到v所有路径的长度的最小值;(2)删掉某条边。

    思路:

    (1)将每个边也转化成一个点,比如边(1,2),转化成(1,3),(3,2)两个边;那么边权看做3的点权;1和2的点权可以看做0;

    (2)反着做。首先将删掉的边都删掉,询问倒着回答,那么就成了加边。

    (3)显然,路径长度就是最小生成树的最大值。因此,首先,将没有删掉的边求一次最小生成树,将最小生成树的边建立动态树。

    (4)对于查询比较简单直接查就行。

    (5)对于添加边(u,v),若u与v之前没有连通,则该边直接加进去就行,其实就是两个子树连在一起;否则,该边加进去之后会出现环,那么需要删掉环上的最大值的边。



    struct node
    {
        int Max,maxNode,val,id,isRev;
        node *c[2],*f;
        
        void reverse()
        {
            isRev^=1;
            swap(c[0],c[1]);
        }
    };


    node a[N],*nullNode;


    void init()
    {
        nullNode=new node();
        nullNode->Max=nullNode->val=nullNode->isRev=0;
        nullNode->c[0]=nullNode->c[1]=nullNode->f=nullNode;
    }


    void pushUp(node *x)
    {
        if(x==nullNode) return;
        x->maxNode=x->id;
        x->Max=x->val;
        
        if(x->c[0]!=nullNode&&x->c[0]->Max>x->Max)
        {
            x->maxNode=x->c[0]->maxNode;
            x->Max=x->c[0]->Max;
        } 
        if(x->c[1]!=nullNode&&x->c[1]->Max>x->Max)
        {
            x->maxNode=x->c[1]->maxNode;
            x->Max=x->c[1]->Max;
        }
    }


    void pushDown(node *x)
    {
        if(x==nullNode) return;
        if(x->isRev)
        {
            if(x->c[0]!=nullNode) x->c[0]->reverse();
            if(x->c[1]!=nullNode) x->c[1]->reverse();
            x->isRev=0;
        }
    }


    int isRoot(node *x)
    {
        if(x->f==nullNode) return 1;
        node *p=x->f;
        return p->c[0]!=x&&p->c[1]!=x;
    }




    void zig(node *x)
    {
        node *p=x->f,*q=p->f;
        p->c[0]=x->c[1];
        if(x->c[1]!=nullNode) x->c[1]->f=p;
        x->c[1]=p;
        p->f=x;
        x->f=q;
        if(q!=nullNode)
        {
            if(q->c[0]==p) q->c[0]=x;
            if(q->c[1]==p) q->c[1]=x;
        }
        pushUp(p);
    }




    void zag(node *x)
    {
        node *p=x->f,*q=p->f;
        p->c[1]=x->c[0];
        if(x->c[0]!=nullNode) x->c[0]->f=p;
        x->c[0]=p;
        p->f=x;
        x->f=q;
        if(q!=nullNode)
        {
            if(q->c[0]==p) q->c[0]=x;
            if(q->c[1]==p) q->c[1]=x;
        }
        pushUp(p);
    }




    void splay(node *x)
    {
        pushDown(x);
        while(!isRoot(x))
        {
            if(!isRoot(x->f))
            {
                pushDown(x->f->f);
                pushDown(x->f);
                pushDown(x);
                if(x->f->f->c[0]==x->f)
                {
                    if(x->f->c[0]==x) zig(x->f),zig(x);
                    else zag(x),zig(x);
                }
                else 
                {
                    if(x->f->c[1]==x) zag(x->f),zag(x);
                    else zig(x),zag(x);
                }
            }
            else
            {
                pushDown(x->f);
                pushDown(x);
                if(x->f->c[0]==x) zig(x);
                else zag(x);
            }
        }
        pushUp(x);
    }




    node *access(node *x)
    {
        node *p=nullNode;
        while(x!=nullNode)
        {
            splay(x);
            x->c[1]=p;
            pushUp(x);
            p=x;
            x=x->f;
        }
        return p;
    }




    void makeRoot(int x)
    {
        access(a+x);
        splay(a+x);
        a[x].reverse();
    }




    void join(int x,int y)
    {
        makeRoot(x); access(a+y); splay(a+y);
        a[x].f=a+y;
    }




    void cut(int x,int y)
    {
        makeRoot(x); access(a+y); splay(a+y);
        a[y].c[0]->f=nullNode;
        a[y].c[0]=nullNode;
        splay(a+y);
    }


    pair<int,int> query(int x,int y)
    {
        makeRoot(y); access(a+x); splay(a+x);
        if(a[y].f==nullNode) return MP(-1,-1);
        access(a+x);
        node *p=a+y,*q=nullNode;
        int Max,maxNode;
        while(p!=nullNode)
        {
            splay(p);
            if(p->f==nullNode)
            {
                Max=p->val;
                maxNode=p->id;
                if(p->c[1]!=nullNode&&p->c[1]->Max>Max)
                {
                    Max=p->c[1]->Max;
                    maxNode=p->c[1]->maxNode;
                }
                if(q!=nullNode&&q->Max>Max)
                {
                    Max=q->Max;
                    maxNode=q->maxNode;
                }
                return MP(maxNode,Max);
            }
            p->c[1]=q;
            q=p;
            pushUp(q);
            p=p->f;
        }
    }


    int W[N];




    int n,m,Q;


    struct OP
    {
        int u,v,op,ans;
    };


    OP b[100005];


    int c[N][2];




    int get()
    {
        int x=0;
        char c=getchar();
        while(c>'9'||c<'0') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x;
    }


    struct E
    {
        int u,v,w,id,flag;
        
        void read()
        {
            u=get(); v=get(); w=get();
            if(u>v) swap(u,v);
            flag=1;
        }
    };


    E edge[N];


    int cmp(E a,E b)
    {
        if(a.u!=b.u) return a.u<b.u;
        return a.v<b.v;
    }


    int find(int u,int v)
    {
        int low=1,high=m,mid;
        while(low<=high)
        {
            mid=(low+high)>>1;
            if(edge[mid].u==u&&edge[mid].v==v) return mid;
            if(edge[mid].u<u||edge[mid].u==u&&edge[mid].v<v) low=mid+1;
            else high=mid-1;
        }
    }


    void Add(int u,int v,int id)
    {
        pair<int,int> p=query(u,v);
        if(p.first!=-1)   
        {
            if(p.second<=W[id]) return;
            cut(p.first,c[p.first][0]);
            cut(p.first,c[p.first][1]);
        }
        join(u,id);
        join(v,id);
    }




    int cmp1(E a,E b)
    {
        return a.w<b.w;
    }


    int fa[N];


    int get(int x)
    {
        if(fa[x]!=x) fa[x]=get(fa[x]);
        return fa[x];
    }


    vector<int> g[N];
    int visit[N];


    void BFS(int u)
    {
        queue<int> Q;
        Q.push(u);
        int i,v;
        while(!Q.empty())
        {
            u=Q.front();
            Q.pop();
            visit[u]=1;
            
            FOR0(i,SZ(g[u]))
            {
                v=g[u][i];
                if(a+v==a[u].f) continue;
                a[v].f=a+u;
                Q.push(v);
            }
        }
    }


    void build()
    {
        sort(edge+1,edge+m+1,cmp1);
        int i,u,v,t;
        FOR1(i,n+m) fa[i]=i;
        FOR1(i,m) if(edge[i].flag)
        {
            u=get(edge[i].u);
            v=get(edge[i].v);
            if(u==v) continue;
            fa[u]=v;
            u=edge[i].u;
            v=edge[i].v;
            t=edge[i].id;
            g[u].pb(t); g[v].pb(t);
            g[t].pb(u); g[t].pb(v);
        }
        FOR1(i,n+m) if(!visit[i]) BFS(i);
        sort(edge+1,edge+m+1,cmp);
    }


    void go()
    {
        int i;
        for(i=Q;i>=1;i--)
        {
            if(b[i].op==1) b[i].ans=query(b[i].u,b[i].v).second;
            else Add(b[i].u,b[i].v,edge[find(b[i].u,b[i].v)].id);
        }
        FOR1(i,Q) if(b[i].op==1) PR(b[i].ans);
    }




    int main()
    {
        n=get(); m=get(); Q=get();
        init();
        int i,u,v,w,t;
        i64 x;
        FOR1(i,m)
        {
            edge[i].read();
            edge[i].id=i+n;
            c[i+n][0]=edge[i].u;
            c[i+n][1]=edge[i].v;
            W[n+i]=edge[i].w;
        }
        sort(edge+1,edge+m+1,cmp);
        FOR1(i,Q)
        {
            b[i].op=get(); 
            b[i].u=get(); 
            b[i].v=get();
            if(b[i].u>b[i].v) swap(b[i].u,b[i].v);
            if(b[i].op==2)
            {
                t=find(b[i].u,b[i].v);
                edge[t].flag=0;
            }
        }
        for(i=1;i<=n+m;i++)
        {
            a[i].c[0]=a[i].c[1]=a[i].f=nullNode;
            a[i].val=a[i].Max=W[i];
            a[i].maxNode=a[i].id=i;
            a[i].isRev=0;
        }
        build();
        go();
    }





  • 相关阅读:
    表达式求解
    block的使用
    UITableView 知识点总结
    UIView 实战习题
    三、 UIView封装的简单动画
    二、 UIButton的使用总结
    一、 UIView的常见属性
    iOS开发网络篇之文件下载、大文件下载、断点下载
    多线程-NSthread
    二.初始化方法
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/3458124.html
Copyright © 2011-2022 走看看