BZOJ 1969 树链剖分+Tarjan缩点
Posted yyjxx2010xyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1969 树链剖分+Tarjan缩点相关的知识,希望对你有一定的参考价值。
发现自己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
以上是关于BZOJ 1969 树链剖分+Tarjan缩点的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )
[bzoj1969] [Ahoi2005]LANE 航线规划
BZOJ1969[Ahoi2005]LANE 航线规划 离线+树链剖分+线段树