• 【BZOJ 1969】 1969: [Ahoi2005]LANE 航线规划 (树链剖分+线段树)


    1969: [Ahoi2005]LANE 航线规划

    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

    HINT

    Source

    【分析】

      hh想出来了。。

      删边不好做,考虑加边,题目保证删完边还是联通的,我们维护一棵树(假设是一棵树)

      假设现在把x,y连起来,假设他们的LCA为z,显然可以把x->y路径上的点全部缩成一个点,加边后这条路径上的边成环,所以之后一定不是关键边。

      事实上呢,不用缩点,直接把两个点的路径的边权清0,即z->x,z->y路径的边清零。

      没有清0的边边权为1,询问就是问x->y路径的边权和。

      用树剖和线段树维护就好了。

      【预处理别人都是MAP什么的,表示不会= =就排了个序搞搞了。。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define Maxn 30010
      8 #define Maxm 100010
      9 
     10 struct node
     11 {
     12     int x,y,next;
     13     int bj,id;
     14 }t[Maxn*2],tt[Maxm*4];
     15 int first[Maxn],len;
     16 
     17 void ins(int x,int y)
     18 {
     19     // printf("%d -> %d
    ",x,y);
     20     t[++len].x=x;t[len].y=y;
     21     t[len].next=first[x];first[x]=len;
     22 }
     23 
     24 struct nnode
     25 {
     26     int l,r,lc,rc,sm;
     27 }tr[Maxn*2];
     28 
     29 void upd(int x)
     30 {
     31     if(tr[x].l==tr[x].r||tr[x].sm!=0) return;
     32     int lc=tr[x].lc,rc=tr[x].rc;
     33     tr[lc].sm=tr[rc].sm=0;
     34 }
     35 
     36 int tot;
     37 int build(int l,int r)
     38 {
     39     int x=++tot;
     40     tr[x].l=l;tr[x].r=r;
     41     if(l!=r)
     42     {
     43         int mid=(l+r)>>1;
     44         tr[x].lc=build(l,mid);
     45         tr[x].rc=build(mid+1,r);
     46     }
     47     else tr[x].lc=tr[x].rc=0;
     48     tr[x].sm=r-l+1;
     49     return x;
     50 }
     51 
     52 void change(int x,int l,int r)
     53 {
     54     if(tr[x].l==l&&tr[x].r==r)
     55     {
     56         tr[x].sm=0;
     57         return;
     58     }
     59     upd(x);
     60     int mid=(tr[x].l+tr[x].r)>>1,lc=tr[x].lc,rc=tr[x].rc;
     61     if(r<=mid) change(lc,l,r);
     62     else if(l>mid) change(rc,l,r);
     63     else
     64     {
     65         change(lc,l,mid);
     66         change(rc,mid+1,r);
     67     }
     68     tr[x].sm=tr[lc].sm+tr[rc].sm;
     69 }
     70 
     71 int query(int x,int l,int r)
     72 {
     73     if(tr[x].sm==0) return 0;
     74     if(tr[x].l==l&&tr[x].r==r) return tr[x].sm;
     75     upd(x);
     76     int mid=(tr[x].l+tr[x].r)>>1,lc=tr[x].lc,rc=tr[x].rc;
     77     if(r<=mid) return query(lc,l,r);
     78     else if(l>mid) return query(rc,l,r);
     79     else return query(lc,l,mid)+query(rc,mid+1,r);
     80 }
     81 
     82 int tp[Maxn],sum[Maxn],son[Maxn],dfn[Maxn],dep[Maxn];
     83 int ff[Maxn];
     84 int cnt;
     85 void dfs(int x,int f)
     86 {
     87     son[x]=0;sum[x]=1;dep[x]=dep[f]+1;
     88     ff[x]=f;
     89     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
     90     {
     91         int y=t[i].y;
     92         dfs(y,x);
     93         sum[x]+=sum[y];
     94         if(son[x]==0||sum[son[x]]<sum[y]) son[x]=y;
     95     }
     96 }
     97 
     98 void dfs2(int x,int tpp)
     99 {
    100     dfn[x]=++cnt;tp[x]=tpp;
    101     if(son[x]) dfs2(son[x],tpp);
    102     for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff[x]&&t[i].y!=son[x])
    103     {
    104         int y=t[i].y;
    105         dfs2(y,y);
    106     }
    107 }
    108 
    109 void fchange(int x,int y)
    110 {
    111     while(tp[x]!=tp[y])
    112     {
    113         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    114         change(1,dfn[tp[x]],dfn[x]);
    115         x=ff[tp[x]];
    116     }
    117     if(dep[x]<dep[y]) swap(x,y);
    118     if(x!=y) change(1,dfn[y]+1,dfn[x]);
    119 }
    120 
    121 int fquery(int x,int y)
    122 {
    123     int ans=0;
    124     while(tp[x]!=tp[y])
    125     {
    126         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    127         ans+=query(1,dfn[tp[x]],dfn[x]);
    128         x=ff[tp[x]];
    129     }
    130     if(dep[x]<dep[y]) swap(x,y);
    131     if(x!=y)
    132     {
    133         // if(dfn[y]+1>dfn[x]) while(1);
    134         ans+=query(1,dfn[y]+1,dfn[x]);
    135     }
    136     return ans;
    137 }
    138 
    139 int fa[Maxn];
    140 int ffa(int x)
    141 {
    142     if(fa[x]!=x) fa[x]=ffa(fa[x]);
    143     return fa[x];
    144 }
    145 
    146 bool cmp(node x,node y)
    147 {
    148     if(x.x==y.x&&x.y==y.y) return x.bj<y.bj;
    149     return (x.x==y.x)?(x.y<y.y):(x.x<y.x);
    150 }
    151 bool cmp2(node x,node y) {return x.id<y.id;}
    152 
    153 int ans[Maxn];
    154 
    155 void solve()
    156 {
    157     int n,m;
    158     scanf("%d%d",&n,&m);
    159     int ll=0;
    160     for(int i=1;i<=m;i++)
    161     {
    162         int x,y;
    163         ll++;
    164         scanf("%d%d",&tt[ll].x,&tt[ll].y);
    165         tt[ll].bj=1;//cha ru
    166     }
    167     int ct=0;
    168     while(1)
    169     {
    170         int cs=0;
    171         scanf("%d",&cs);
    172         if(cs==-1) break;
    173         ll++;
    174         scanf("%d%d",&tt[ll].x,&tt[ll].y);
    175         if(cs==0) tt[ll].bj=-1;//shan chu
    176         else tt[ll].bj=0;//xun wen
    177         tt[ll].id=++ct;
    178     }
    179     sort(tt+1,tt+1+ll,cmp);
    180     for(int i=1;i<=n;i++) fa[i]=i;
    181     ct++;
    182     int pp=0;
    183     for(int i=1;i<=ll;i++)
    184     {
    185         if(tt[i].bj==0) continue;
    186         if(tt[i].bj==1)
    187         {
    188             if(pp==0||tt[i].x!=tt[pp].x||tt[i].y!=tt[pp].y)
    189             {
    190                 if(ffa(tt[i].x)==ffa(tt[i].y))
    191                 {
    192                     tt[i].bj=-1;
    193                     tt[i].id=ct;
    194                 }
    195                 else
    196                 {
    197                     ins(tt[i].x,tt[i].y);
    198                     ins(tt[i].y,tt[i].x);
    199                     fa[ffa(tt[i].x)]=tt[i].y;
    200                 }
    201             }
    202         }
    203         pp=i;
    204     }
    205     dep[0]=0;
    206     dfs(1,0);cnt=0;
    207     dfs2(1,1);
    208     build(1,n);
    209     sort(tt+1,tt+1+ll,cmp2);
    210     // return ;
    211     ans[0]=0;
    212     for(int i=ll;i>=1;i--)
    213     {
    214         if(tt[i].bj==1) continue;
    215         if(tt[i].bj==-1)
    216         {
    217             fchange(tt[i].x,tt[i].y);
    218         }
    219         else
    220         {
    221             ans[++ans[0]]=fquery(tt[i].x,tt[i].y);
    222         }
    223     }
    224     for(int i=ans[0];i>=1;i--) printf("%d
    ",ans[i]);
    225 }
    226 
    227 int main()
    228 {
    229     solve();
    230     return 0;
    231 }
    View Code

    2017-03-06 14:04:26

  • 相关阅读:
    Centos7下thinkphp5.0环境配置
    win10蓝牙鼠标无法连接,需pin码
    thinkphp5自带workerman应用
    php文件加密(screw方式)
    centos修改ssh默认端口号的方法
    修改CentOS ll命令显示时间格式
    在线编辑器的原理简单示例
    [转载]提升SQLite数据插入效率低、速度慢的方法
    linux 客户机挂载vitualbox共享文件夹
    virtualbox linux客户机中安装增强功能包缺少kernel头文件问题解决
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6509663.html
Copyright © 2020-2023  润新知