BNUOJ ->Borrow Classroom(LCA)
B. Borrow Classroom
Time Limit: 5000ms
Memory Limit: 262144KB
每年的BNU校赛都会有两次赛前培训,为此就需要去借教室,由于SK同学忙于出题,这个事情就由小Q同学来跑腿。SK同学准备从宿舍出发,把借教室的单子交给小Q同学让他拿去教务处盖章,但是何老师突然发现SK同学好像借错教室了,想抢在借教室的单子被送到教务处之前拦截下来。
现在把校园抽象成一棵个节点的树,每条边的长度都是一个单位长度,从到编号,其中教务处位于号节点,接下来有个询问,每次询问中SK同学会从号节点出发,到号节点找到小Q同学并将借教室的单子交给他,然后小Q同学再从号节点出发前往教务处,何老师会从号节点出发开始拦截。
所有人在一个单位时间内最多走一个单位距离,只要何老师在单子还没被送到教务处之前遇到拿着单子的同学都算拦截成功,如果小Q同学已经到了教务处,那么由于小Q同学手速极快,单子会被立即交上去,即使何老师到了教务处也无济于事,你需要判断何老师是否能够拦截成功。
Input
第一行是一个正整数,表示测试数据的组数,
对于每组测试数据,
第一行是两个整数,分别表示节点数和询问数,
接下来行,每行包含两个整数,表示和之间有一条边相连,保证这些边能构成一棵树,
接下来行,每行包含三个整数,表示一个询问,其中是何老师所在位置,是SK同学所在位置,是小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 }