Codeforces Round #620 (Div. 2) E 树上两点最小距离(LCA倍增)

题意:

给一个n点的数,以1为根的树,

询问m个x,y,a,b,k

问x,y两点暂时联通,a点到b点能不能刚好满足过k条线

能输出yes,不能输出no

思路:

树上两点之间的距离用lca算出来,因为可以反复横跳,所以只要两点之间的距离小于等于k,然后与k的奇偶性一样就是yes

一共有三条路

dis(a,b)

dis(a,x)+dis(y,b)+1

dis(a,y)+dis(x,b)+1

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define il inline
 5 #define it register int
 6 #define inf 0x3f3f3f3f
 7 #define lowbit(x) (x)&(-x)
 8 #define mem(a,b) memset(a,b,sizeof(a))
 9 #define mod 998244353
10 const int maxn=1e5+10;
11 struct node{
12     int next,v;
13 }a[maxn<<1];
14 int t,m,n,head[maxn],tot,x,y,a1,b,k,f,depth[maxn],fa[maxn][20];
15 void add(int u,int v){
16     a[tot].next=head[u];
17     a[tot].v=v;head[u]=tot++;
18 }
19 void build(int uu){
20     queue<int>q;
21     depth[uu]=1;
22     q.push(1);
23     while(!q.empty()){
24         int u=q.front();q.pop();
25         for(it i=head[u];~i;i=a[i].next){
26             int v=a[i].v;
27             if(depth[v]==-1){
28                 depth[v]=depth[u]+1;q.push(v);
29                 fa[v][0]=u;
30                 for(it j=1;j<=19;j++){
31                     int arc=fa[v][j-1];
32                     fa[v][j]=fa[arc][j-1];
33                 }
34             }
35         }
36     }
37 }
38 int lca(int x,int y){
39     if(depth[x]<depth[y])swap(x,y);
40     for(it i=19;i>=0;i--){
41         if(depth[fa[x][i]]>=depth[y]){
42             x=fa[x][i];
43         }
44     }
45     if(x==y)return x;
46     for(it i=19;i>=0;i--){
47         if(fa[x][i]!=fa[y][i]){
48             x=fa[x][i];
49             y=fa[y][i];
50         }
51     }
52     return fa[x][0];
53 }
54 int dis(int u,int v){
55     int d=lca(u,v);
56     return depth[u]+depth[v]-2*depth[d];
57 }
58 int main(){
59     mem(head,-1);mem(depth,-1);tot=0;
60     scanf("%d",&n);
61     for(it i=0;i<n-1;i++){
62         int u,v;
63         scanf("%d%d",&u,&v);add(u,v);add(v,u);
64     }
65     depth[0]=0;build(1);
66     scanf("%d",&m);
67     while(m--){
68         scanf("%d%d%d%d%d",&x,&y,&a1,&b,&k);
69         int kk=k;k%=2;
70         int d1=dis(a1,b),d2=dis(a1,x)+dis(y,b)+1,d3=dis(a1,y)+dis(x,b)+1;
71         if((d1%2==k && kk>=d1) || (d2%2==k && kk>=d2)||(d3%2==k && kk>=d3)){printf("YES\n");}
72         else{printf("NO\n");}
73     }
74     return 0;
75 }
76 /*
77 5
78 1 2
79 2 3
80 3 4
81 4 5
82 5
83 1 3 1 2 2
84 1 4 1 3 2
85 1 4 1 3 3
86 4 2 3 3 9
87 5 2 3 3 9
88 YES
89 YES
90 NO
91 YES
92 NO
93 */
View Code

猜你喜欢

转载自www.cnblogs.com/luoyugongxi/p/12318566.html