HDU 6203 ping ping ping LCA + dfs序 + 树状数组(区间更新单点查询)

来源:互联网 发布:2017淘宝双11技术汇总 编辑:程序博客网 时间:2024/05/16 09:13

传送门:HDU 6203

题意:给出n+1 个点的树,其中有若干个点无法通过,导致 p 组顶点对(u, v)之间无法连通。问无法通行的点最少有多少个。

思路:对p组(u,v)顶点对求LCA,并按LCA的深度排序,从深度最大的开始处理,然后在dfs序上进行标记,若当前顶点对之间已经不可达,则直接跳过,否则将其LCA在dfs序上标记出来。

具体标记及判断方法详见:点击打开链接

树状数组区间更新单点查询就很类似于imos和思想,也很常用。

代码:

#include<bits/stdc++.h>  using namespace std;  #define MAXN 10050#define MAXM 10050#define inf 0x3f3f3f3f  typedef pair<int,int>P;  int dep[MAXN], pre_ord[MAXN], post_ord[MAXN];int f[20][MAXN], pre[MAXN];  int cnt, tid;  struct node  {      int v, next;      node(int _v = 0, int _next = 0) : v(_v), next(_next) {}  }mp[MAXM * 2]; void init()  {      cnt = tid = 0;    memset(pre, -1, sizeof(pre));}void add(int u, int v)  {      mp[cnt] = node(v, pre[u]), pre[u] = cnt++;      mp[cnt] = node(u, pre[v]), pre[v] = cnt++;}  void dfs(int u, int fa)  {      dep[u] = dep[fa] + 1;    pre_ord[u] = ++tid;    for(int i = pre[u]; ~i; i = mp[i].next)      {          int v = mp[i].v;          if(v == fa) continue;          dfs(v, u);          f[0][v] = u;      }    post_ord[u] = ++tid;}    int lca_init(int n)  {      dep[1] = 1;      dfs(1, 0);      int k = 0,t = 1;      while(t <= n)t <<= 1,k++;      for(int i=0;i+1<k;i++)      {          for(int j=1;j<=n;j++)          {             f[i+1][j] = f[i][f[i][j]];          }      }      return k;  }int lca(int u, int v, int MAX)  {      if(dep[u] < dep[v]) swap(u, v);      int k = dep[u] - dep[v];      for(int i = 0;i < MAX; i++)      {          if((k >> i) & 1)          u = f[i][u];      }      if(u == v)return u;      for(int i = MAX - 1;i >= 0; i--)      while(f[i][u] != f[i][v])      {          u = f[i][u];          v = f[i][v];      }      return f[0][u];  }struct query{    int u, v, lca;    query(int _u = 0, int _v = 0, int _lca = 0) : u(_u), v(_v), lca(_lca) {}    bool operator < (query x) const    {        return dep[lca] > dep[x.lca];    }}Q[MAXN * 5];int bit[MAXN << 1];void update(int i, int x){    while(i <= tid)    {        bit[i] += x;        i += i & -i;    }}int sum(int i){    int res = 0;    while(i)    {        res += bit[i];        i -= i & -i;    }    return res;}int main(){    int T, n, u, v, q;    while(~scanf("%d", &n))    {        init();        memset(bit, 0, sizeof(bit));        for(int i = 1; i <= n; i++)        {            scanf("%d %d", &u, &v);            add(++u, ++v);        }        n++;        int up = lca_init(n);        scanf("%d", &q);        for(int i = 0; i < q; i++)        {            scanf("%d %d", &u, &v);            u++,v++;             Q[i] = query(u, v, lca(u, v, up));        }        sort(Q, Q + q);        int is, ans = 0;        for(int i = 0; i < q; i++)        {            is = sum(pre_ord[Q[i].u]) + sum(pre_ord[Q[i].v]);            if(!is)            {                ans++;                update(pre_ord[Q[i].lca], 1);                update(post_ord[Q[i].lca] + 1, -1);            }        }        cout << ans << endl;    }     return 0;}


原创粉丝点击