zoukankan      html  css  js  c++  java
  • [AHOI2005]LANE 航线规划

    题目链接:戳我
    LCT维护连通性的一类题目。
    首先看到删边+询问联通相关立刻想到倒着做,将删边操作替换成加边操作。
    用LCT来维护。因为LCT是关于树的数据结构,不能维护图怎么办呢。
    我们有一个很显然的认识是,倒着做的话,如果加入的一条边的两个端点已经在一个联通块里面了,那么两点之间原先连的所有边应该都不是关键边了。我们求的是关键边的个数,所以直接赋成权值,如果是关键边就是1,如果不是就是0;询问的时候求路径和就可以了。
    但是LCT维护边权的时候不能直接把边权的值赋到点上,要新开一个节点来记录。
    更改的操作直接记录到根节点就行了,树进行下次旋转splay操作之前会全部把标记push_down掉,同时也就进行了路径上所有边、点的修改。
    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #define MAXN 400010
    using namespace std;
    int n,m,tot,cnt;
    int s[MAXN];
    map<pair<int,int>,int>mm;
    struct Node{int val,rev,sum,tag,ff,ch[2];}t[MAXN];
    struct Edge{int u,v,name;}edge[MAXN];
    struct Edge2{int u,v,name,ans;}que[MAXN];
    
    inline void push_up(int x){t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+t[x].val;}
    inline bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
    inline void update(int x){t[x].sum=t[x].val=0;t[x].tag=1;}
    inline void push_rev(int x){swap(t[x].ch[0],t[x].ch[1]);t[x].rev^=1;}
    inline void rotate(int x)
    {
        int y=t[x].ff;
        int z=t[y].ff;
        int k=t[y].ch[1]==x;
        if(!isroot(y)) t[z].ch[t[z].ch[1]==y]=x; t[x].ff=z;
        t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].ff=y;
        t[x].ch[k^1]=y; t[y].ff=x;
        push_up(y),push_up(x);
    }
    inline void push_down(int x)
    {
        if(t[x].rev)
        {
            if(t[x].ch[0]) t[t[x].ch[0]].rev^=1;
            if(t[x].ch[1]) t[t[x].ch[1]].rev^=1;
            swap(t[x].ch[0],t[x].ch[1]);
            t[x].rev^=1;
        }
        if(t[x].tag)
        {
            if(t[x].ch[0]) update(t[x].ch[0]);
            if(t[x].ch[1]) update(t[x].ch[1]);
            t[x].tag=0;
        }
    }
    inline void splay(int x)
    {
        s[tot=1]=x;
        for(int i=x;!isroot(i);i=t[i].ff) s[++tot]=t[i].ff;
        while(tot) push_down(s[tot--]);
        while(!isroot(x))
        {
            int y=t[x].ff;
            int z=t[y].ff;
            if(!isroot(y))
                ((t[y].ch[0]==x)^(t[z].ch[0]==y))?rotate(x):rotate(y);
            rotate(x);
        }
    }
    inline void access(int x)
    {
        for(int y=0;x;y=x,x=t[x].ff)
            splay(x),t[x].ch[1]=y,push_up(x);
    }
    inline void makeroot(int x){access(x);splay(x);t[x].rev^=1;}
    inline void split(int x,int y){makeroot(x);access(y);splay(y);}
    inline void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;push_up(y);}
    inline void link(int x,int y){makeroot(x);t[x].ff=y;}
    inline int findroot(int x)
    {   
        access(x);
        splay(x);
        while(t[x].ch[0]) push_down(x),x=t[x].ch[0];
        return x;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            if(u>v) swap(u,v);
            edge[i]=(Edge){u,v,0};
            mm[make_pair(u,v)]=i;
            t[i+n].val=1;
        }
        int cur,u,v;
        scanf("%d",&cur);
        while(cur!=-1)
        {
            scanf("%d%d",&u,&v);
            if(u>v) swap(u,v);
            que[++cnt]=(Edge2){u,v,cur,0};
            if(cur==0) edge[mm[make_pair(u,v)]].name=1;
            scanf("%d",&cur);
        }
        for(int i=1;i<=m;i++)
        {
            if(edge[i].name==1) continue;
            if(findroot(edge[i].u)!=findroot(edge[i].v)) 
                link(edge[i].u,i+n),link(edge[i].v,i+n);
            else split(edge[i].u,edge[i].v),update(edge[i].v);
        }
        for(int i=cnt;i>=1;i--)
        {
            if(que[i].name==1) split(que[i].u,que[i].v),que[i].ans=t[que[i].v].sum;
            else split(que[i].u,que[i].v),update(que[i].v);
        }
        for(int i=1;i<=cnt;i++)
            if(que[i].name)
                printf("%d
    ",que[i].ans);
        return 0;
    }
    
  • 相关阅读:
    MySQL通过RPM安装
    HDU4279(2012年天津网络赛---数论分析题)
    Redis实战
    顺序环形队列的各种基本运算
    cocos2d_随手篇1_关于ccTouchBegan的调用
    URAL 1019
    Redis实战之Redis + Jedis
    dataGridView控件--未将对象引用设置添加到对象的实例
    创建 router 连通 subnet- 每天5分钟玩转 OpenStack(100)
    配置 L3 agent
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10288254.html
Copyright © 2011-2022 走看看