zoukankan      html  css  js  c++  java
  • HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203

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

    解法:按照询问的LCA深度排序,然后顺序标记每个询问的LCA。根据所给的树(任意点为根)预处理出每个点的前序 DFS 序和后序 DFS 序(需统一标号),及点的深度。根据 p 组 U V 处理每组两点的 LCA 。压入优先队列(LCA 深度大的点优先出队)。对于出队的 U V 及其对应的 LCA ,判断点 U 或点 V 是否在之前已禁止的某点的子树中,对于某点U如果在禁止通行的点P的子树中,则L[P]<=L[U]<=R[U]<=R[P]一定成立。所以可以利用树状数组区间更新单点查询,对于每个禁止通行点标记区间L[P],R[P]的所有节点。查询的时候如果L[U]被标记,说明U,V已经被隔断。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 20100;
    typedef long long LL;
    vector <int> G[maxn];
    int n, m, dfsclk, c[maxn], fa[maxn][21], dep[maxn], L[maxn], R[maxn];
    bool vis[maxn];
    struct node{
        int u,v,uv;
        node(){}
        node(int u,int v,int uv):u(u),v(v),uv(uv){}
        bool operator<(const node &rhs)const{
            return dep[uv]<dep[rhs.uv];
        }
    };
    void dfs(int x){
        vis[x]=1;
        L[x]=++dfsclk;
        for(int i=0; i<G[x].size(); i++){
            int v=G[x][i];
            if(!vis[v]){
                dep[v]=dep[x]+1;
                fa[v][0]=x;
                dfs(v);
            }
        }
        R[x]=++dfsclk;
    }
    void init(){
        for(int j=1; j<=20; j++)
            for(int i=1; i<=n; i++)
                fa[i][j] = fa[fa[i][j-1]][j-1];
    }
    int LCA(int u, int v){
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=20; i>=0; i--){
           if((dep[u]-dep[v])&(1<<i))
              u=fa[u][i];
        }
        if(u==v) return u;
        for(int i=20; i>=0; i--){
            if(fa[u][i]!=fa[v][i]){
                u=fa[u][i];
                v=fa[v][i];
            }
        }
        return fa[u][0];
    }
    int lowbit(int x){
        return x&(-x);
    }
    void add(int x, int v){
        while(x<maxn){
            c[x]+=v;
            x+=lowbit(x);
        }
    }
    void update(int x, int y, int z){
        add(x, z);
        add(y+1, -z);
    }
    int query(int x){
        int ret=0;
        while(x>0){
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    int main()
    {
        while(~scanf("%d", &n))
        {
            memset(c, 0, sizeof(c));
            memset(vis, 0, sizeof(vis));
            memset(dep, 0, sizeof(dep));
            for(int i=0; i<=n+1; i++) G[i].clear();
            for(int i=1; i<=n; i++){
                int u,v;
                scanf("%d %d", &u,&v);
                u++,v++;
                G[u].push_back(v);
                G[v].push_back(u);
            }
            n++;
            dfsclk = 0;
            dfs(1);
            init();
            priority_queue <node> q;
            scanf("%d", &m);
            while(m--){
                int u, v;
                scanf("%d %d", &u,&v);
                u++;
                v++;
                int uv = LCA(u, v);
                q.push(node(u,v,uv));
            }
            int ans=0;
            while(!q.empty()){
                node now = q.top();
                q.pop();
                int flag = query(L[now.u])+query(L[now.v]);
                if(flag==0){
                    ans++;
                    update(L[now.uv],R[now.uv],1);
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    关于Jupyter Notebook默认起始目录设置无效的解决方法
    关于二叉树中度为0与度为2节点数关系证明
    LeetCode第[3]题(Java):Longest Substring Without Repeating Characters 标签:Linked List
    数据结构,物理结构,存储结构,逻辑结构的区分
    条件变量 sync.Cond
    defer 的常用场景
    switch...case... 语句中的类型转换
    golang 切片和数组在for...range中的区别
    golang 并发顺序输出数字
    Golang 中哪些值是不可以寻址的
  • 原文地址:https://www.cnblogs.com/spfa/p/7515837.html
Copyright © 2011-2022 走看看