zoukankan      html  css  js  c++  java
  • BZOJ1969: [Ahoi2005]LANE 航线规划

    题解 :LCT动态缩环即可

    /**************************************************************
        Problem: 1969
        User: c20161007
        Language: C++
        Result: Accepted
        Time:856 ms
        Memory:6692 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    #define ll long long
    const int MAXN=3e4+10;
    const int NM=1e5+10;
    using namespace std;
    int rt[MAXN],size[MAXN],minn[MAXN],ch[MAXN][2],res[MAXN],pre[MAXN];
    int key[MAXN],fa[MAXN];
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    void newnode(int pos){
        rt[pos]=1;size[pos]=1;minn[pos]=key[pos]=pos;ch[pos][0]=ch[pos][1]=0;res[pos]=0;pre[pos]=0;fa[pos]=pos;
    }
    int find1(int x){
        if(x==fa[x])return x;
        else return fa[x]=find1(fa[x]);
    }
    void reverse(int r){
        if(!r)return ;
        swap(ch[r][0],ch[r][1]);
        res[r]^=1;
    }
    void push(int x){
        if(res[x]){
        reverse(ch[x][0]);
        reverse(ch[x][1]);
        res[x]=0;
        }
    }
    void up(int x){
        minn[x]=min(minn[ch[x][0]],minn[ch[x][1]]);
        minn[x]=min(minn[x],key[x]);
        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
    }
    void P(int x){
        if(!rt[x])P(find1(pre[x]));
        push(x);
    }
    void rotate(int x,int kind){
        int y=find1(pre[x]);
        ch[y][!kind]=ch[x][kind];pre[ch[x][kind]]=y;
        if(rt[y])rt[x]=1,rt[y]=0;
        else ch[find1(pre[y])][ch[find1(pre[y])][1]==y]=x;
        pre[x]=find1(pre[y]);ch[x][kind]=y;pre[y]=x;up(y);
    }
    void splay(int x){
        P(x);
        while(!rt[x]){
        if(rt[find1(pre[x])])rotate(x,ch[find1(pre[x])][0]==x);
        else{
            int y=find1(pre[x]);int kind=ch[find1(pre[y])][0]==y;
            if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
            else rotate(y,kind),rotate(x,kind);
        }
        }
        up(x);
    }
    void access(int x){
        int y=0;//cout<<x<<"-----===="<<endl;
        while(x){
        splay(x);
        if(ch[x][1])pre[ch[x][1]]=x,rt[ch[x][1]]=1,ch[x][1]=0;
        if(rt[y])rt[y]=0;
        ch[x][1]=y;up(x);
        y=x;x=find1(pre[x]);
        }
    }
    void mroot(int x){
        access(x);splay(x);reverse(x);
    }
    bool pd(int u,int v){
        while(pre[u])u=find1(pre[u]);
        while(pre[v])v=find1(pre[v]);
        return u==v;
    }
    void Link(int u,int v){
        mroot(u);mroot(v);pre[u]=v;
    }
    vector<int>vec;
    void dfs(int v){
        if(!v)return ;
        vec.push_back(v);
        dfs(ch[v][0]);
        dfs(ch[v][1]);
    }
    void destory(int u,int v){
        mroot(u);access(v);splay(v);
     //   cout<<u<<" "<<v<<endl;
      //  cout<<"sb"<<endl;
        int tx=minn[v];
       // cout<<tx<<endl;
        dfs(v);
       // cout<<tx<<endl;
        for(int i=0;i<vec.size();i++)fa[vec[i]]=tx,ch[vec[i]][0]=ch[vec[i]][1]=0,rt[vec[i]]=1;
      //  cout<<endl;
        //cout<<tx<<endl;
        for(int i=0;i<vec.size();i++)pre[vec[i]]=0;
        vec.clear();
        up(tx);
    }
    void slove(int u,int v){
        u=find1(u);v=find1(v);
       // cout<<pd(u,v)<<endl;
        if(pd(u,v)) destory(u,v);
        else Link(u,v);
    }
    int querty(int u,int v){
        u=find1(u);v=find1(v);
        //cout<<u<<" "<<v<<endl;
        mroot(u);access(v);
       // cout<<"sb"<<endl;
        splay(v);
        return size[v]-1;
    }
    typedef struct node{
        int op,u,v;
    }node;
    node que[NM];
    set<pair<int,int> >s;
    set<pair<int,int> >::iterator ite;
    stack<int>ss;
    int main(){
        minn[0]=1e9+7;
        int n,m;n=read();m=read();
        for(int i=1;i<=n;i++)newnode(i);
        int u,v,op;
        for(int i=1;i<=m;i++){u=read(),v=read();
        if(u>v)swap(u,v);
        s.insert(make_pair(u,v));}
        int cnt=0;
        while(scanf("%d",&op)!=EOF){
        if(op==-1)break;
        que[++cnt].op=op;que[cnt].u=read();que[cnt].v=read();
        if(que[cnt].op==1)continue;
    //  cout<<cnt<<endl;
    //  cout<<que[cnt].op<<" "<<que[cnt].u<<" "<<que[cnt].v<<endl;
        if(que[cnt].u>que[cnt].v)swap(que[cnt].u,que[cnt].v);
        s.erase(s.find(make_pair(que[cnt].u,que[cnt].v)));
        }
     //   cout<<cnt<<endl;
        for(ite=s.begin();ite!=s.end();ite++){
        slove(ite->first,ite->second);
        }
     //   cout<<"sb"<<endl;
      //  cout<<minn[1]<<endl;
        for(int i=cnt;i>=1;i--){
        if(que[i].op==1){
            ss.push(querty(que[i].u,que[i].v));
    //      cout<<"sb"<<endl;
        }
        else slove(que[i].u,que[i].v);
        }
      //  cout<<"sb"<<endl;
        while(!ss.empty()){
        printf("%d
    ",ss.top());
        ss.pop();
        }
        return 0;
    }
    

    1969: [Ahoi2005]LANE 航线规划

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 637  Solved: 287
    [Submit][Status][Discuss]

    Description

    对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系。 星际空间站的Samuel II巨型计算机经过长期探测,已经锁定了Samuel星系中许多星球的空间坐标,并对这些星球从1开始编号1、2、3……。 一些先遣飞船已经出发,在星球之间开辟探险航线。 探险航线是双向的,例如从1号星球到3号星球开辟探险航线,那么从3号星球到1号星球也可以使用这条航线。 例如下图所示: 在5个星球之间,有5条探险航线。 A、B两星球之间,如果某条航线不存在,就无法从A星球抵达B星球,我们则称这条航线为关键航线。 显然上图中,1号与5号星球之间的关键航线有1条:即为4-5航线。 然而,在宇宙中一些未知的磁暴和行星的冲撞,使得已有的某些航线被破坏,随着越来越多的航线被破坏,探险飞船又不能及时回复这些航线,可见两个星球之间的关键航线会越来越多。 假设在上图中,航线4-2(从4号星球到2号星球)被破坏。此时,1号与5号星球之间的关键航线就有3条:1-3,3-4,4-5。 小联的任务是,不断关注航线被破坏的情况,并随时给出两个星球之间的关键航线数目。现在请你帮助完成。

    Input

    第一行有两个整数N,M。表示有N个星球(1< N < 30000),初始时已经有M条航线(1 < M < 100000)。随后有M行,每行有两个不相同的整数A、B表示在星球A与B之间存在一条航线。接下来每行有三个整数C、A、B。C为1表示询问当前星球A和星球B之间有多少条关键航线;C为0表示在星球A和星球B之间的航线被破坏,当后面再遇到C为1的情况时,表示询问航线被破坏后,关键路径的情况,且航线破坏后不可恢复; C为-1表示输入文件结束,这时该行没有A,B的值。被破坏的航线数目与询问的次数总和不超过40000。

    Output

    对每个C为1的询问,输出一行一个整数表示关键航线数目。 注意:我们保证无论航线如何被破坏,任意时刻任意两个星球都能够相互到达。在整个数据中,任意两个星球之间最多只可能存在一条直接的航线。

    Sample Input

    5 5
    1 2
    1 3
    3 4
    4 5
    4 2
    1 1 5
    0 4 2
    1 5 1
    -1

    Sample Output

    1
    3

  • 相关阅读:
    iStylePDF c#集成开发示例
    纯js 实现 HTML 元素拖拽,
    前端自动滚动
    双向选择排序(暂定)
    uniapp 分享链接
    Could not find a declaration file for module 'vue-xxx'.
    精通JavaScript(重点内容笔记)更新中...
    如何让DIV模块随着页面固定和不固定
    序列不包含任何匹配元素
    PHPStorm配置Apache服务器(wampServer 版)
  • 原文地址:https://www.cnblogs.com/wang9897/p/9439175.html
Copyright © 2011-2022 走看看