码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1969 树链剖分+Tarjan缩点

时间:2016-06-03 17:14:44      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:

发现自己Tarjan的板子有错误.发现可以用Map直接删去边,Get.

听说std是双连通、LCA、并查集、离线思想、用BIT维护dfs序和并查集维护LCA的动态缩点的好题

技术分享
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <vector>
  6 #include <map>
  7 #include <set>
  8 #include <stack>
  9 #define mp make_pair
 10 #define pa pair<int,int>
 11 #define pb push_back
 12 #define fi first
 13 #define se second
 14 using namespace std;
 15 inline void Get_Int(int &x)
 16 {
 17     x=0;  char ch=getchar(); int f=1;
 18     while (ch<0 || ch>9) {if (ch==-) f=-1; ch=getchar();}
 19     while (ch>=0 && ch<=9) {x=x*10+ch-0; ch=getchar();} x*=f;
 20 }
 21 inline void Put_Int(int x)
 22 {
 23     char ch[20]; int top=0;
 24     if (x==0) ch[++top]=0;
 25     while (x) ch[++top]=x%10+0,x/=10;
 26     while (top) putchar(ch[top--]); putchar(\n);
 27 }
 28 //===================================================
 29 const int Maxm=200100;
 30 const int Maxn=30100;
 31 const int Maxop=40100;
 32 struct EDGE{int to,next;}edge[Maxm];
 33 struct OP{int type,u,v;}Op[Maxop];
 34 int head[Maxn],siz[Maxn],father[Maxn],top[Maxn],dep[Maxn],num[Maxn],sum[Maxn<<2],clr[Maxn<<2];
 35 int Belong[Maxn],Low[Maxn],Dfn[Maxn],Ans[Maxn];
 36 int Stack[Maxn];
 37 int stamp,Stamp,cnt,scc,apex,Q,n,m,u,v;
 38 bool vis[Maxn];
 39 map<pa,bool> Edge;
 40 vector<pa> V;
 41 set <pa> S;
 42 inline void Add(int u,int v) 
 43 {edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
 44 inline int Max(int x,int y) {return x>y?x:y;}
 45 inline int Min(int x,int y) {return x>y?y:x;}
 46 inline void Build_G()
 47 {
 48     map<pa,bool>::iterator it;
 49     for (it=Edge.begin();it!=Edge.end();it++)
 50         if (it->se) 
 51             Add(it->fi.fi,it->fi.se);
 52 }
 53 inline void Clear_G()
 54 {    
 55     map<pa,bool>::iterator it;
 56     for (it=Edge.begin();it!=Edge.end();it++)
 57         if (it->se) it->se=false;
 58 }
 59 //=================================================
 60 
 61 void Dfs1(int u)
 62 {
 63     vis[u]=true; siz[u]=1;
 64     for (int i=head[u];i!=-1;i=edge[i].next)
 65         if (!vis[edge[i].to]) 
 66         {
 67             father[edge[i].to]=u;
 68             dep[edge[i].to]=dep[u]+1;
 69             Dfs1(edge[i].to);
 70             siz[u]+=siz[edge[i].to];
 71         }
 72 }
 73 void Dfs2(int u,int chain)
 74 {
 75     num[u]=++stamp; top[u]=chain; vis[u]=true; int k=0;
 76     for (int i=head[u];i!=-1;i=edge[i].next)
 77         if (!vis[edge[i].to] && (siz[edge[i].to]>siz[k] || k==0)) k=edge[i].to;
 78     if (k==0) return;
 79     Dfs2(k,chain);
 80     for (int i=head[u];i!=-1;i=edge[i].next)
 81         if (!vis[edge[i].to] && edge[i].to!=k) Dfs2(edge[i].to,edge[i].to);
 82 }
 83 
 84 inline int Lca(int u,int v) 
 85 {
 86     while (true)
 87     {
 88         if (top[u]==top[v]) return dep[u]>dep[v]?v:u;
 89         if (dep[top[u]]>dep[top[v]]) u=father[top[u]]; else v=father[top[v]];
 90     }
 91 }
 92 //==================================================
 93 
 94 inline void push_up(int o) {sum[o]=sum[o<<1]+sum[o<<1|1];}
 95 inline void Clr(int o) {clr[o]=1; sum[o]=0;}
 96 inline void push_down(int o) {if (clr[o]) Clr(o<<1),Clr(o<<1|1); clr[o]=0;}
 97 void Modify(int o,int l,int r,int p,int q)
 98 {
 99     if (l==p && r==q)
100     {
101         sum[o]=0;
102         clr[o]=1;
103         return;
104     }
105     push_down(o);
106     int mid=(l+r)>>1;
107     if (q<=mid) Modify(o<<1,l,mid,p,q);
108     if (p>=mid+1) Modify(o<<1|1,mid+1,r,p,q);
109     if (p<=mid && q>=mid+1) Modify(o<<1,l,mid,p,mid),Modify(o<<1|1,mid+1,r,mid+1,q);
110     push_up(o);
111 }
112 int Query(int o,int l,int r,int p,int q)
113 {
114     if (l==p && r==q) return sum[o];
115     push_down(o);
116     int mid=(l+r)>>1;
117     if (q<=mid) return Query(o<<1,l,mid,p,q);
118     if (p>=mid+1) return Query(o<<1|1,mid+1,r,p,q);
119     if (p<=mid && q>=mid+1) return Query(o<<1,l,mid,p,mid)+Query(o<<1|1,mid+1,r,mid+1,q);
120 }
121 void Build(int o,int l,int r)
122 {
123     if (l==r)
124     {
125         sum[o]=1; 
126         return;
127     }
128     int mid=(l+r)>>1;
129     Build(o<<1,l,mid),Build(o<<1|1,mid+1,r);
130     push_up(o);
131 }
132 
133 //=================================================
134 void Tree_Modify(int u,int v)
135 {
136     while (top[u]!=top[v])
137     {
138         Modify(1,1,scc,num[top[u]],num[u]);
139         u=father[top[u]];
140     }
141     Modify(1,1,scc,num[v],num[u]);
142 }
143 int Tree_Query(int u,int v) 
144 {
145     int ret=0;
146 
147     while (top[u]!=top[v])
148     {
149          ret+=Query(1,1,scc,num[top[u]],num[u]);
150         u=father[top[u]];
151     }
152     ret+=Query(1,1,scc,num[v],num[u]);
153     return ret;
154 }
155 //=================================================
156 void Tarjan(int u,int fa)
157 {
158     Low[u]=Dfn[u]=++Stamp; Stack[++apex]=u;
159     for(int i=head[u];i!=-1;i=edge[i].next)
160         if (edge[i].to!=fa)
161         {
162             int v=edge[i].to;
163             if(!Dfn[v])
164             {
165                 Tarjan(v,u);
166                 Low[u]=Min(Low[u],Low[v]);
167                 if(Low[v]>Dfn[u])
168                 {
169                     scc++;
170                     while(true) {int x=Stack[apex--]; Belong[x]=scc; if(x==v)break;}
171                 }
172             }
173             else Low[u]=Min(Low[u],Dfn[v]);
174         }
175     if(fa<0)
176     {
177         scc++;
178         while(true){int x=Stack[apex--]; Belong[x]=scc;    if(x==u)break;}
179     }
180 }
181 //=================================================
182 
183 int main()
184 {
185     //freopen("c.in","r",stdin);
186     Get_Int(n),Get_Int(m);
187     for (int i=1;i<=m;i++)
188         Get_Int(u),Get_Int(v),Edge[mp(u,v)]=true,Edge[mp(v,u)]=true;
189 
190     for (Q=1;;Q++)
191     {
192         Get_Int(Op[Q].type); if (Op[Q].type==-1) break;
193         Get_Int(Op[Q].u),Get_Int(Op[Q].v);
194         if (Op[Q].type==0) Edge[mp(Op[Q].u,Op[Q].v)]=false,Edge[mp(Op[Q].v,Op[Q].u)]=false;
195     }
196     Q--;
197     stamp=Stamp=cnt=0;
198     memset(head,-1,sizeof(head));
199     memset(vis,false,sizeof(vis));
200     memset(Low,0,sizeof(Low));
201     memset(Dfn,0,sizeof(Dfn));
202 
203     Build_G();
204     Tarjan(1,-1);
205     Clear_G();
206     for (int i=1;i<=n;i++)
207         for (int j=head[i];j!=-1;j=edge[j].next)
208             if (Belong[i]!=Belong[edge[j].to]) 
209             {
210                 if (S.count(mp(Belong[i],Belong[edge[j].to]))==1) continue;
211                 S.insert(mp(Belong[i],Belong[edge[j].to]));
212                 S.insert(mp(Belong[edge[j].to],Belong[i]));
213                 V.pb(mp(Belong[i],Belong[edge[j].to]));
214                 V.pb(mp(Belong[edge[j].to],Belong[i]));
215             }
216     
217 
218     memset(head,-1,sizeof(head));cnt=0;
219     for (int i=0;i<V.size();i++) Add(V[i].fi,V[i].se);
220     father[1]=1;dep[1]=1;
221     memset(vis,false,sizeof(vis)),Dfs1(1);
222     memset(vis,false,sizeof(vis)),Dfs2(1,1);
223     Build(1,1,scc);
224     for (int i=Q;i>=1;i--)
225     {
226         int p=Belong[Op[i].u],q=Belong[Op[i].v];
227         if (Op[i].type==0)
228         {
229             if (p==q) continue;
230             int t=Lca(p,q);
231             if (t==p) 
232             {
233                 int k=0;
234                 for (int j=head[t];j!=-1;j=edge[j].next)
235                     if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
236 
237                 Tree_Modify(q,k);
238                 continue;
239             }
240 
241             if (t==q) 
242             {
243                 int k=0;
244                 for (int j=head[t];j!=-1;j=edge[j].next)
245                     if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
246                 Tree_Modify(p,k);
247                 continue;
248             }
249             int r,s;
250             for (int j=head[t];j!=-1;j=edge[j].next)
251                 if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {r=edge[j].to; break;}
252             for (int j=head[t];j!=-1;j=edge[j].next)
253                 if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {s=edge[j].to; break;}
254             Tree_Modify(p,r),Tree_Modify(q,s);
255         } else 
256         if (Op[i].type==1)
257         {
258             if (p==q) {Ans[i]=0; continue;}
259             int t=Lca(p,q);
260             if (t==p) 
261             {
262                 int k=0;
263                 for (int j=head[t];j!=-1;j=edge[j].next)
264                     if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
265                 Ans[i]=Tree_Query(q,k);
266                 continue;
267             }
268             if (t==q) 
269             {
270                 int k=0;
271                 for (int j=head[t];j!=-1;j=edge[j].next)
272                     if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
273                 Ans[i]=Tree_Query(p,k);
274                 continue;
275             }
276             
277             int r,s;
278             for (int j=head[t];j!=-1;j=edge[j].next)
279                 if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {r=edge[j].to; break;}
280             for (int j=head[t];j!=-1;j=edge[j].next)
281                 if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {s=edge[j].to; break;}
282             Ans[i]=Tree_Query(p,r)+Tree_Query(q,s);
283         }
284     }
285     for (int i=1;i<=Q;i++) 
286         if (Op[i].type==1) Put_Int(Ans[i]);
287     return 0;
288 }
289         
290     
傻逼树剖280+系列

 

BZOJ 1969 树链剖分+Tarjan缩点

标签:

原文地址:http://www.cnblogs.com/yyjxx2010xyu/p/5556777.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!