HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

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

题意  :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点。

题解  :求每个点对的LCA,然后根据LCA的深度排序。从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1。

#include<Bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
int N, Q;
int c[maxn], In[maxn], Out[maxn], cnt;
struct Edge
{
    int id, next;
    Edge(int id = 0, int next = 0): id(id), next(next) {}
} E[maxn << 1]; //双向边
int head[maxn], tot;
void initEdge()
{
    memset(c, 0, sizeof(c));
    cnt = 0;
    for(int i = 0; i <= N; i++) head[i] = -1;
    tot = 0;
}
void addEdge(int u, int v)
{
    E[tot] = Edge(v, head[u]);
    head[u] = tot++;
}
int siz[maxn], top[maxn], dep[maxn], fa[maxn];
int clk;//需要初始化
void DFS1(int u, int p)
{
    In[u] = ++cnt;
    dep[u] = dep[p] + 1;
    fa[u] = p, siz[u] = 1;
    for(int k = head[u]; k != -1; k = E[k].next)
    {
        int id = E[k].id;
        if(id == p) continue;
        DFS1(id, u);
        siz[u] += siz[id];
    }
    Out[u] = cnt;
}
void DFS2(int u, int p)
{
    int son = -1;
    for(int k = head[u]; k != -1; k = E[k].next)//找重儿子
    {
        int id = E[k].id;
        if(id == p)continue;
        if(son == -1 || siz[id] > siz[son]) son = id;
    }
    if(son != -1)
    {
        top[son] = top[u];
        DFS2(son, u);
    }
    for(int k = head[u]; k != -1; k = E[k].next)
    {
        int id = E[k].id;
        if(id == p || id == son)continue;
        top[id] = id;
        DFS2(id, u);
    }
}
int LCA(int x, int y)
{
    while(top[x] != top[y])
    {
        if(dep[top[x]] < dep[top[y]]) swap(x, y);
        x = fa[top[x]];
    }
    if(dep[x] > dep[y]) swap(x, y);
    return x;
}




struct node
{
    int u, v, lca;
    bool operator < (const node &T) const
    {
        return dep[lca] > dep[T.lca];
    }
} qry[50050];
int low_Bit(int x)
{
    return x & -x;
}
void update(int x, int val)
{
    while(x <= N)
    {
        c[x] += val;
        x += low_Bit(x);
    }
}
int get_sum(int x)
{
    int ret = 0;
    while(x > 0)
    {
        ret += c[x];
        x -= low_Bit(x);
    }
    return ret;
}
int main()
{
    while(~scanf("%d", &N))
    {
        N++;
        initEdge();
        for(int i = 1; i <= N - 1; i++)
        {
            int u, v;
            scanf("%d %d", &u, &v);
            u++, v++;
            addEdge(u, v), addEdge(v, u);
        }
        DFS1(1, 0),top[1] = 1,DFS2(1, 0);
        scanf("%d", &Q);
        for(int i = 1; i <= Q; i++)
        {
            scanf("%d %d", &qry[i].u, &qry[i].v);
            qry[i].u++, qry[i].v++;
            qry[i].lca = LCA(qry[i].u, qry[i].v);
        }
        sort(qry + 1, qry + 1 + Q);
        int ans = 0;
        for(int i = 1; i <= Q; i++)
        {
            int u = qry[i].lca;
            int ret = get_sum(In[qry[i].u]) + get_sum(In[qry[i].v]);
            if(ret) continue;
            ans++;
            update(In[u], 1);
            update(Out[u] + 1, -1);
        }
        printf("%d\n", ans);
    }
    return 0;
}

  

posted @ 2017-09-20 16:45  _Mickey  阅读(168)  评论(0编辑  收藏  举报