ural1752 Tree 2
Tree 2
Time limit: 1.0 second
Memory limit: 64 MB
Memory limit: 64 MB
Consider a tree consisting of n vertices. A distance between two vertices is the minimal number of edges in a path connecting them. Given a vertex vi and distance di find a vertex ui such that distance between vi and ui equals to di.
Input
The first line contains the number of vertices n (1 ≤ n ≤ 20000) and the number of queries q(1 ≤ q ≤ 50000). Each of the following n − 1 lines describes an edge and contains the numbers of vertices connected by this edge. Vertices are numbered from 1 to n. The next q lines describe the queries. Each query is described by a line containing two numbers vi (1 ≤ vi ≤ n) and di(0 ≤ di ≤ n).
Output
You should output q lines. The i-th line should contain a vertex number ui, the answer to the i-th query. If there are several possible answers, output any of them. If there are no required vertices, output 0 instead.
Sample
input | output |
---|---|
9 10 1 8 1 5 1 4 2 7 2 5 3 6 5 9 6 9 5 4 8 1 4 3 2 4 9 3 1 1 5 2 3 5 6 4 7 3 |
0 1 2 3 4 5 6 7 8 9
|
分析:参考自http://www.lai18.com/content/7044719.html;
首先找到树的直径的两个端点,因为如果在端点到询问点之间没有答案,那么肯定没有答案;
然后根据端点建树,若存在答案,则需要求出距离询问点为d的点,而这个点就在树根与询问点之间且距询问点为d;
然后关键的地方就是对每个点,保留距离为2^k的祖先,存放在祖先数组中,这样就可以利用倍增求出答案了;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <map> #include <queue> #include <stack> #include <vector> #include <list> #define rep(i,m,n) for(i=m;i<=n;i++) #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++) #define mod 1000000000 #define inf 0x3f3f3f3f #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define Lson L, mid, rt<<1 #define Rson mid+1, R, rt<<1|1 const int maxn=2e4+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;} int n,m,k,t,s,q,dis[maxn][2],fa[maxn][2],anc[maxn][30][2],ma,id; vi a[maxn]; void dfs(int now,int pre) { for(int x:a[now]) { if(x!=pre) { dis[x][0]=dis[now][0]+1; if(dis[x][0]>ma)ma=dis[x][0],id=x; dfs(x,now); } } } void dfs1(int now,int pre,int p) { for(int x:a[now]) { if(x!=pre) { dis[x][p]=dis[now][p]+1; fa[x][p]=now; dfs1(x,now,p); } } } void init() { memset(anc,-1,sizeof anc); for(int k=0;k<2;k++) { for(int i=1;i<=n;i++) { anc[i][0][k]=fa[i][k]; } for(int j=1;(1<<j)<n;j++) { for(int i=1;i<=n;i++) { if(anc[i][j-1][k]!=-1) { anc[i][j][k]=anc[anc[i][j-1][k]][j-1][k]; } } } } } int query(int p,int now,int d) { for(int i=29;i>=0;i--) { if(d>=(1LL<<i)) { d-=(1LL<<i); now=anc[now][i][p]; } if(d==0)return now; } } int main() { int i,j; id=1; scanf("%d%d",&n,&q); rep(i,1,n-1)scanf("%d%d",&j,&k),a[j].pb(k),a[k].pb(j); dfs(1,-1);s=id; ma=0;id=1; memset(dis,0,sizeof dis); dfs(s,-1);t=id; memset(dis,0,sizeof dis); dfs1(s,-1,0);dfs1(t,-1,1); init(); while(q--) { int u,d; scanf("%d%d",&u,&d); if(dis[u][0]>=d)printf("%d\n",query(0,u,d)); else if(dis[u][1]>=d)printf("%d\n",query(1,u,d)); else puts("0"); } //system("Pause"); return 0; }