A and B and Lecture Rooms CodeForces - 519E

http://codeforces.com/problemset/problem/519/E

给一个树图 每次询问给两个点xy 问有多少点和两点距离相等

先判两点距离奇偶 如果为偶数则不存在某点和此两点距离相等

为奇数则求出与xy之间路径上的中点 假设当前中点就是树根的话 就用n减去根节点所有包含xy的直接子树的节点数就好 因为这两棵子树上的点肯定是偏向于某一方的

虽然我们建的是有根树 但是思想是一样的 搞一搞就好 详见代码 具体怎么找某个节点的k级祖先 可以通过求lca时的不同层化同层来实现

注意xy可能相等

#include <bits/stdc++.h>
using namespace std;

struct node
{
    int v;
    int next;
};

node edge[200010];
int dp[100010][20];
int first[100010],deep[100010],sum[100010];
int n,q,num;

void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
}

void dfs(int cur,int fa)
{
    int i,v;
    sum[cur]=1;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v!=fa)
        {
            dp[v][0]=cur;
            deep[v]=deep[cur]+1;
            dfs(v,cur);
            sum[cur]+=sum[v];
        }
    }
    return;
}

void solve()
{
    int i,j;
    dp[1][0]=0;
    deep[1]=1;
    dfs(1,0);
    for(j=1;(1<<j)<=n;j++)
    {
        for(i=1;i<=n;i++)
        {
            dp[i][j]=dp[dp[i][j-1]][j-1];
        }
    }
    return;
}

int getlca(int u,int v)
{
    int i;
    if(deep[u]<deep[v]) swap(u,v);
    for(i=log2(n);i>=0;i--)
    {
        if(deep[dp[u][i]]>=deep[v]) u=dp[u][i];
    }
    if(u==v) return u;
    for(i=log2(n);i>=0;i--)
    {
        if(dp[u][i]!=dp[v][i])
        {
            u=dp[u][i];
            v=dp[v][i];
        }
    }
    return dp[u][0];
}

int getpos(int u,int dep)
{
    int i;
    for(i=log2(n);i>=0;i--)
    {
        if(deep[dp[u][i]]>=dep) u=dp[u][i];
    }
    return u;
}

int main()
{
    int i,u,v,lca,dis,mid,p,ans;
    scanf("%d",&n);
    memset(first,-1,sizeof(first));
    num=0;
    for(i=1;i<=n-1;i++)
    {
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }
    solve();
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d%d",&u,&v);
        if(u==v) printf("%d\n",n);
        else if(abs(deep[u]-deep[v])%2==1) printf("0\n");
        else
        {
            lca=getlca(u,v);
            if(deep[u]==deep[v])
            {
                dis=deep[u]-deep[lca];
                ans=n;
                p=getpos(u,deep[u]-(dis-1));
                ans-=sum[p];
                p=getpos(v,deep[v]-(dis-1));
                ans-=sum[p];
            }
            else
            {
                dis=(deep[u]+deep[v]-2*deep[lca])/2;
                if(deep[u]<deep[v]) swap(u,v);
                mid=getpos(u,deep[u]-dis);
                ans=sum[mid];
                p=getpos(u,deep[u]-(dis-1));
                ans-=sum[p];
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82421977
今日推荐