zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    [姿势] 关于Ubuntu16.04安装前后
    [题解] poj 1716 Integer Intervals (差分约束+spfa)
    [题解] hdu 2433 Travel (BFS)
    [题解] poj 3169 Layout (差分约束+bellmanford)
    [题解] poj 3660 Cow Contest (floyd)
    [题解] hdu 1142 A Walk Through the Forest (dijkstra最短路 + 记忆化搜索)
    [题解] poj 1724 ROADS (dijkstra最短路+A*搜索)
    [BZOJ1491][NOI2007]社交网络 floyd
    [BZOJ2064]分裂 状压dp
    [BZOJ3585]mex 主席树
  • 原文地址:https://www.cnblogs.com/hnooo/p/10016132.html
Copyright © 2011-2022 走看看