HDU 6203 ping ping ping (LCA + 树状数组, 2017 ACM/ICPC Asia Regional Shenyang Online)

来源:互联网 发布:宝贝上淘宝首页 编辑:程序博客网 时间:2024/05/16 10:12

Problem

n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连通。问无法通行的点最少有多少个。

Idea

根据所给的树(任意点为根)预处理出每个点的前序 DFS 序和后序 DFS 序(需统一标号),及点的深度。

根据 p 组 U V 处理每组两点的 LCA 。压入优先队列(LCA 深度大的点优先出队)。

对于出队的 U V 及其对应的 LCA ,判断点 U 或点 V 是否在之前已禁止的某点的子树中。

判断点 U 或点 V 是否在之前已禁止的某点的子树中。

处理方式:由于之前已经处理出每个点的前后序 DFS 序 In[] 和 Out[] 。

对于某点 U 若在已禁止通行点 P 的子树中,则 In[P]In[U]Out[U]Out[P] 一定成立。

故利用树状数组区间更新单点查询。对每个禁止通行点 P ,标记区间 [In[P],Out[P]] 中所有点。查询时,若点 In[U] 被标记,则说明 U V 已经被隔断。

同时,由于优先处理 LCA 深度大的点,不会出现点 U V 同时在同一个被禁止通行点 P 的子树内。

若 U ,V 均不在被禁止的点在子树内,则禁止 U V 的 LCA 点,同时对答案贡献 +1 。

Code

#include<bits/stdc++.h>using namespace std;#define LL long longvector <int> g[10100];int father[10100][22]={0};int depth[10100]={0};int bin[20200];int In[10100];int Out[10100];int n,m;struct Node{    int u,v,uv;    Node(){}    Node(int _u,int _v,int _uv):u(_u),v(_v),uv(_uv){}    friend bool operator<(Node n1,Node n2){        return depth[n1.uv]<depth[n2.uv];    }};bool visit[10010]={false};int root,cnt;void dfs(int u){    int i;    visit[u]=true;    In[u]=++cnt;    for (i=0;i<g[u].size();i++){        int v=g[u][i];        if ( !visit[v] ){            depth[v]=depth[u]+1;            father[v][0]=u;            dfs(v);        }    }    Out[u]=++cnt;}void bz(){    int i,j;    for (j=1;j<=20;j++)        for (i=1;i<=n;i++)            father[i][j]=father[father[i][j-1]][j-1];} int LCA(int u,int v) {    if ( depth[u]<depth[v] ) {        int temp=u;        u=v;        v=temp;    }     int dc=depth[u]-depth[v];    int i;    for (i=0;i<=20;i++)    {        if ( (1<<i) & dc)         u=father[u][i];    }    if (u==v) return u;     for (i=20;i>=0;i--){        if (father[u][i]!=father[v][i])        {            u=father[u][i];            v=father[v][i];        }    }    u=father[u][0];    return u;}inline int lowbit(int x) {  return x & -x;  }inline int sum(int x) {    int res = 0;    while(x)    res += bin[x],  x -= lowbit(x);;    return res;}inline void add(int x, int w) {    while(x < 20200)    bin[x] += w, x += lowbit(x);    }inline int update(int x, int y, int w) {    add(x, w);  add(y+1, -w);}int main(){    int u,v,p;    while(scanf("%d", &n)!=EOF) {        memset(bin,0,sizeof(bin));        memset(visit,0,sizeof(visit));        for(int i=0;i<=n+1;++i)            g[i].clear();        for(int i=1;i<=n;++i){            scanf("%d %d",&u,&v);            u++, v++;            g[u].push_back(v);            g[v].push_back(u);        }        n++;        cnt=0;        dfs(1);        bz();        scanf("%d",&p);        priority_queue<Node> q;        while(!q.empty())   q.pop();        Node tmp;        while(p--){            scanf("%d %d",&u,&v);            u++;    v++;            int uv=LCA(u,v);            tmp = Node(u,v,uv);            q.push(tmp);        }        int ans=0;        while(!q.empty()){            tmp=q.top();            q.pop();            int flg=sum(In[tmp.u])+sum(In[tmp.v]);            if(!flg){                ans++;                update(In[tmp.uv],Out[tmp.uv],1);            }        }        printf("%d\n",ans);    }}
阅读全文
0 0