Cpp环境【CQ-NOIP2016四校联考模拟题(一)P3】树上的询问

【问题描述】  

  现有一棵 n 个节点的棵, 树上每条边的长度均为 1。 给出 m 个询问, 每次询问两个节 点 x,y, 求树上到 x,y 两个点距离相同的节点数量。

【输入格式】  

  第一个整数 n, 表示树有 n 个点。
  接下来 n-1 行每行两整数 a, b, 表示从 a 到 b 有一条边。
  接下来一行一个整数 m, 表示有 m 个询问。
  接下来 m 行每行两整数 x, y, 询问到 x 和 y 距离相同的点的数量。

【输出格式】  

  共 m 行, 每行一个整数表示询问的答案。

【输入样例】  

7
1 2
1 3
2 4
2 5
3 6
3 7
3
1 2
4 5
2 3

【输出样例】  

0
5
1

【数据范围】  

对于 30%的数据, 满足 n≤50, m≤50
对于 60%的数据, 满足 n≤1000, m≤1000
对于 100%的数据, 满足 n≤100000, m≤100000

【来源】    

noip2016四校联考,巴蜀命题

#include
#include
#include
#include
#include
#define maxn 100005
using namespace std;
vector<int>g[maxn];
int n,m,fa[maxn],depth[maxn],dist[maxn],sz[maxn],depthnum[maxn];
int marka,markb;
//depthnum[i]=深度为i的节点数量
//dist[i]=所有深度小于i的节点的数量
//sz[i]=以节点i为根的子树的节点总数 
void read(int &x)
{
    x=0;
    char ch=getchar();
    while(ch<'0' || ch>'9') ch=getchar();
    while(ch>='0' && ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
}

void build_tree(int i)
{
    for(int j=0;jint k=g[i][j];
        if(fa[k])continue;
        fa[k]=i;depth[k]=depth[i]+1;
        build_tree(k);
        sz[i]+=sz[k];
    }
    sz[i]++;//i节点包括在以i为根的子树里 
}

int LCA(int a,int b)
{
    while(depth[a]>depth[b])    a=fa[a];
    while(a!=b) marka=a,a=fa[a],markb=b,b=fa[b];
    return a;
}

void solve()
{
    read(m);
    while(m--)
    {
        int a,b;
        read(a);read(b);
        if(depth[b]>depth[a])   swap(a,b);

        if(a==b)    printf("%d\n",n);
        else 
        {
            int root=LCA(a,b),da=depth[root]-depth[a],db=depth[root]-depth[b];
            if((da+db)%2)   printf("0\n");  
            else if(depth[a]==depth[b]) printf("%d\n",n-sz[marka]-sz[markb]);   
            else
            {
                int d=da+db;//a与b的距离 
                int mid=depth[a]+d/2,now=a,last=a;
                while(depth[now]!=mid)  last=now,now=fa[now];
                printf("%d\n",sz[now]-sz[last]);
            }
        }
    }
}

int main()
{
//  freopen("in.txt","r",stdin);
//  freopen("Tree.out","w",stdout);
    read(n);
    for(int i=1;iint x,y;
        read(x);read(y);
        g[x].push_back(y);
        g[y].push_back(x);
    }
    fa[1]=1;
    build_tree(1);
    solve();
    return 0;   
}

你可能感兴趣的:(数据结构之二,树形结构,难度评级,Patience,Required)