NOIP模拟(20171023)T2 一样远

来源:互联网 发布:软件测试简单吗 编辑:程序博客网 时间:2024/05/03 06:59

求树上离给定两点a,b一样远的点的个数
点数n105,询问数m105
首先,如果a=b,那么n个点都是答案
如果ab,将从a到b的链提出来,易得链中点及其子树到a、b距离均相等
显然,我们不能暴力跳树高找中点,考虑倍增
注意当lca是链中点时lca的祖先节点及祖先节点的其他子树上的点也是答案
复杂度O(nlog2n+mlog2n)

#include<bits/stdc++.h>#define LEN 100005using namespace std;inline int getint(){    int x=0,p=1;    char c=getchar();    while(!isdigit(c)){        if(c=='-')p=-1;        c=getchar();    }    while(isdigit(c)){        x=(x<<3)+(x<<1)+(c^'0');        c=getchar();    }    return x*p;}int n;struct tree{    int fa[20],dep,size;    vector<int>road;}t[LEN];void dfs(int cur){    t[cur].size=1;    for(int i=0;i<t[cur].road.size();++i){        int v=t[cur].road[i];        if(v==t[cur].fa[0])continue;        t[v].fa[0]=cur;        t[v].dep=t[cur].dep+1;        dfs(v);        t[cur].size+=t[v].size;    }}void make_fa(){    for(int i=1;i<19;++i){        for(int j=1;j<=n;++j){            t[j].fa[i]=t[t[j].fa[i-1]].fa[i-1];        }    }}inline void work(int a,int b){    if((t[a].dep-t[b].dep)%2){        cout<<0<<"\n";        return;    }    if(a==b){        cout<<n<<"\n";        return;    }    if(t[a].dep==t[b].dep){        for(int i=18;i>=0;--i){            if(t[a].fa[i]!=t[b].fa[i]){                a=t[a].fa[i],b=t[b].fa[i];            }        }        cout<<n-t[a].size-t[b].size<<"\n";    }    else{        if(t[a].dep<t[b].dep)swap(a,b);        int left=(t[a].dep-t[b].dep)/2;        int lca,ta=a,tb=b;        for(int i=18;i>=0;--i){            if(t[t[a].fa[i]].dep>=t[b].dep)a=t[a].fa[i];        }        if(a==b)lca=b;        else{            for(int i=18;i>=0;--i){                if(t[a].fa[i]!=t[b].fa[i]){                    a=t[a].fa[i],b=t[b].fa[i];                }            }            lca=t[a].fa[0];        }        a=ta,b=tb;        int dis=t[a].dep-t[lca].dep;        int need=dis-left-1;        for(int i=18;i>=0;--i){            if(need&(1<<i)){                a=t[a].fa[i];            }        }        cout<<t[t[a].fa[0]].size-t[a].size<<"\n";    }}int main(){    n=getint();    for(int i=1;i<n;++i){        int a=getint(),b=getint();        t[a].road.push_back(b);        t[b].road.push_back(a);    }    int root=1;    dfs(1);    make_fa();    int m=getint();    while(m--){        work(getint(),getint());    }    return 0;}

ps:cout << endl 会TLE,强烈吐槽评测机

原创粉丝点击