【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\n",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\n",ans[i]);
225 }
226 
227 int main()
228 {
229     solve();
230     return 0;
231 }
View Code

 

2017-03-06 14:04:26

posted @ 2017-03-06 13:57  konjak魔芋  阅读(243)  评论(0编辑  收藏  举报