BNUOJ ->Borrow Classroom(LCA)

B. Borrow Classroom

Time Limit: 5000ms
Memory Limit: 262144KB

每年的BNU校赛都会有两次赛前培训,为此就需要去借教室,由于SK同学忙于出题,这个事情就由小Q同学来跑腿。SK同学准备从宿舍出发,把借教室的单子交给小Q同学让他拿去教务处盖章,但是何老师突然发现SK同学好像借错教室了,想抢在借教室的单子被送到教务处之前拦截下来。

现在把校园抽象成一棵n个节点的树,每条边的长度都是一个单位长度,从1n编号,其中教务处位于1号节点,接下来有q个询问,每次询问中SK同学会从B号节点出发,到C号节点找到小Q同学并将借教室的单子交给他,然后小Q同学再从C号节点出发前往教务处,何老师会从A号节点出发开始拦截。

所有人在一个单位时间内最多走一个单位距离,只要何老师在单子还没被送到教务处之前遇到拿着单子的同学都算拦截成功,如果小Q同学已经到了教务处,那么由于小Q同学手速极快,单子会被立即交上去,即使何老师到了教务处也无济于事,你需要判断何老师是否能够拦截成功。

Input

第一行是一个正整数T(\leq 5),表示测试数据的组数,

对于每组测试数据,

第一行是两个整数n,q(1\leq n,q \leq 100000),分别表示节点数和询问数,

接下来n-1行,每行包含两个整数x,y(1\leq x,y \leq n),表示xy之间有一条边相连,保证这些边能构成一棵树,

接下来q行,每行包含三个整数A,B,C(1 \leq A,B,C \leq n),表示一个询问,其中A是何老师所在位置,B是SK同学所在位置,C是小Q同学所在位置,保证小Q同学初始不在教务处。

Output

对于每个询问,输出一行,如果何老师能成功拦截则输出"YES"(不含引号),否则输出"NO"(不含引号)。

Sample Input

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

Sample Output

YES
NO
这就是lca的裸题呀 因为自己一个地方导致无限wa
就是 求出b->c->1的距离 t1 和b->1的距离 t2
if(t1<t2)no
if(t1>t2)yes
if(t1==t2){lca(c,a)==1->no else->yes}
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<map>
  8 #include<set>
  9 #include<vector>
 10 #include<cstdlib>
 11 #include<string>
 12 typedef long long ll;
 13 typedef unsigned long long LL;
 14 using namespace std;
 15 const double pi=acos(-1.0);
 16 const int N=200000+10;
 17 const double eps=0.000000001;
 18 int head[N];
 19 int cnt;
 20 struct node{
 21     int to,next,w;
 22 }edge[2*N];
 23 int d[N*2];
 24 int dp[3*N][30];
 25 int t1;
 26 int dep[N*2],pos[N*2],f[N*2];
 27 void init(){
 28     memset(head,-1,sizeof(head));
 29     memset(pos,-1,sizeof(pos));
 30     memset(d,0,sizeof(d));
 31     cnt=0;
 32     t1=0;
 33 }
 34 void add(int u,int v,int w){
 35     edge[cnt].to=v;
 36     edge[cnt].next=head[u];
 37     edge[cnt].w=w;
 38     head[u]=cnt++;
 39 }
 40 void init_RMQ(int n){
 41     for(int i=1;i<=n;i++)dp[i][0]=i;
 42     for(int j=1;(1<<j)<=n;j++)
 43     for(int i=1;i+(1<<j)-1<=n;i++)
 44     if(dep[dp[i][j-1]]<dep[dp[i+(1<<j-1)][j-1]])dp[i][j]=dp[i][j-1];
 45     else
 46         dp[i][j]=dp[i+(1<<j-1)][j-1];
 47 }
 48 int RMQ(int l,int r){
 49     int k=0;
 50     while((1<<k+1)<=r-l+1)k++;
 51     if(dep[dp[l][k]]<dep[dp[r-(1<<k)+1][k]])return dp[l][k];
 52     else
 53         return dp[r-(1<<k)+1][k];
 54 }
 55 int lca(int u,int v){
 56     if(pos[u]>pos[v])return f[RMQ(pos[v],pos[u])];
 57     else
 58         return f[RMQ(pos[u],pos[v])];
 59 }
 60 void DFS(int x,int deep){
 61     f[t1]=x;
 62     dep[t1]=deep;
 63     pos[x]=t1++;
 64     for(int i=head[x];i!=-1;i=edge[i].next){
 65         int v=edge[i].to;
 66         if(pos[v]==-1){
 67             d[v]=d[x]+1;
 68             DFS(v,deep+1);
 69             f[t1]=x;
 70             dep[t1++]=deep;
 71         }
 72 
 73     }
 74 }
 75 int main(){
 76     int t;
 77     scanf("%d",&t);
 78     int n,q;
 79     while(t--){
 80         init();
 81         scanf("%d%d",&n,&q);
 82         for(int i=1;i<=n-1;i++){
 83             int u,v;
 84             scanf("%d%d",&u,&v);
 85             add(u,v,1);add(v,u,1);
 86         }
 87         DFS(1,0);
 88         init_RMQ(3*n-1);
 89         while(q--){
 90             int a,b,c;
 91             scanf("%d%d%d",&a,&b,&c);
 92             if(b==1&&c==1){cout<<"NO"<<endl;continue;}
 93             int ans1=d[b]+2*d[c]-2*d[lca(c,b)];
 94             int ans2=d[a];
 95             if(ans2<ans1)printf("YES\n");
 96             else if(ans2==ans1){
 97                 if(lca(a,c)==1)cout<<"NO"<<endl;
 98                 else{
 99                     cout<<"YES"<<endl;
100                 }
101             }
102             else{
103                 cout<<"NO"<<endl;
104             }
105         }
106     }
107     return 0;
108 }

 



posted on 2017-04-22 21:48  见字如面  阅读(217)  评论(0编辑  收藏  举报

导航