1. 程式人生 > >CF983E NN country [倍增][LCA][樹狀陣列]

CF983E NN country [倍增][LCA][樹狀陣列]

題意:

  $n$個城市,從$1$到$n$標號,$n$個城市構成一棵樹。

  有$m$條雙向公交路線,對於每條路線,公交沿著兩個終點站之間的最短路徑行駛並會在沿途各站停車。從一個城市只能坐公交前往其他城市。

  有$q$個詢問:從一個城市到另一個城市要搭乘多少趟公交?不能到達輸出$-1$。


 

對於每個詢問$x,y$,求出$z=lca(x,y)$。

先從$x$和$y$出發到達$z$下方的城市$x'$和$y'$使得再坐一趟車可到$z$,記步數和為$s$。倍增,預處理$f[i][j]$表示從$i$出發坐$2^{j}$趟車最上能到達的位置。

若$x'$可坐車到$y'$則答案為$s+1$,否則答案為$s+2$。

考慮dfs過程中用樹狀陣列按dfs序維護,若$x'$的子樹中終點站在$y'$子樹內的車,那麼可以坐一趟車到達。預處理時把公交和詢問分別掛在對應端點上。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 using namespace std;
  6 const int N=200010,K=19;
  7 struct ask {
  8     int y,id,s;
  9     ask () {}
10 ask (int y,int id,int s):y(y),id(id),s(s) {} 11 }; 12 int n,m,q,x,y,z,f[N][K],ans[N],c[N],sum[N]; 13 int cnt,dfn[N],fa[N],son[N],top[N],dep[N],size[N]; 14 int p,head[N],to[N],nxt[N]; 15 vector<int> h[N]; 16 vector<ask> A[N]; 17 inline int read() { 18 int re=0; char ch=getchar();
19 while (ch<'0'||ch>'9') ch=getchar(); 20 while (ch>='0'&&ch<='9') re=re*10+ch-48,ch=getchar(); 21 return re; 22 } 23 inline void add(int x,int y) { 24 to[++p]=y; nxt[p]=head[x]; head[x]=p; 25 } 26 void tree_add(int x) {for (; x<=n; x+=(x&-x)) ++c[x];} 27 int tree_sum(int x) {int re=0; for (; x; x-=(x&-x)) re+=c[x]; return re;} 28 void dfs1(int x) { 29 size[x]=1; dfn[x]=++cnt; 30 for (int i=head[x]; i; i=nxt[i]) { 31 dep[to[i]]=dep[x]+1; 32 dfs1(to[i]); 33 size[x]+=size[to[i]]; 34 if (size[to[i]]>size[son[x]]) son[x]=to[i]; 35 } 36 } 37 void dfs2(int x,int tp) { 38 top[x]=tp; 39 if (son[x]) dfs2(son[x],tp); 40 for (int i=head[x]; i; i=nxt[i]) { 41 if (to[i]==son[x]) continue; 42 dfs2(to[i],to[i]); 43 } 44 } 45 void dfs3(int x) { 46 for (int i=head[x]; i; i=nxt[i]) { 47 dfs3(to[i]); 48 if (dep[f[to[i]][0]]<dep[f[x][0]]) f[x][0]=f[to[i]][0]; 49 } 50 } 51 void dfs4(int x) { 52 for (int i=0; i<A[x].size(); i++) { 53 A[x][i].s=tree_sum(dfn[A[x][i].y]+size[A[x][i].y]-1)-tree_sum(dfn[A[x][i].y]-1); 54 } 55 for (int i=0; i<h[x].size(); i++) tree_add(dfn[h[x][i]]); 56 int tmp; 57 for (int i=head[x]; i; i=nxt[i]) dfs4(to[i]); 58 for (int i=0; i<A[x].size(); i++) { 59 tmp=tree_sum(dfn[A[x][i].y]+size[A[x][i].y]-1)-tree_sum(dfn[A[x][i].y]-1); 60 if (tmp==A[x][i].s) ans[A[x][i].id]++; 61 } 62 } 63 int lca(int a,int b) { 64 while (top[a]!=top[b]) { 65 if (dep[top[a]]>dep[top[b]]) swap(a,b); 66 b=fa[top[b]]; 67 } 68 if (dep[a]>dep[b]) swap(a,b); 69 return a; 70 } 71 int main() { 72 n=read(); 73 for (int i=2; i<=n; i++) add(fa[i]=read(),i); 74 dfs1(1); dfs2(1,1); 75 m=read(); 76 for (int i=1; i<=n; i++) f[i][0]=i; 77 for (int i=1; i<=m; i++) { 78 x=read(); y=read(); 79 h[x].push_back(y); h[y].push_back(x); 80 z=lca(x,y); 81 if (dep[z]<dep[f[x][0]]) f[x][0]=z; 82 if (dep[z]<dep[f[y][0]]) f[y][0]=z; 83 } 84 dfs3(1); 85 for (int j=1; j<K; j++) 86 for (int i=1; i<=n; i++) 87 f[i][j]=f[f[i][j-1]][j-1]; 88 q=read(); 89 for (int i=1; i<=q; i++) { 90 x=read(); y=read(); z=lca(x,y); 91 if (x==y) continue; 92 if (f[x][K-1]!=f[y][K-1]) {ans[i]=-1; continue;} 93 for (int j=K-1; j>=0; j--) { 94 if (dep[f[x][j]]>dep[z]) ans[i]+=(1<<j),x=f[x][j]; 95 if (dep[f[y][j]]>dep[z]) ans[i]+=(1<<j),y=f[y][j]; 96 } 97 ans[i]++; 98 if (z!=x && z!=y) A[x].push_back(ask(y,i,0)); 99 } 100 dfs4(1); 101 for (int i=1; i<=q; i++) printf("%d\n",ans[i]); 102 return 0; 103 }