码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

时间:2020-03-29 01:40:42      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:break   return   contest   更新   处理   log   查询   namespace   wap   

https://codeforces.com/contest/1328/problem/E

题目所描述的是一棵树,题中已明示1为root结点。

题目可以转化为,是否存在一条路径,满足集合中的k个点到路径的距离小于等于1?

思路:

1.首先倍增离线预处理出结点深度,便于后续在线询问LCA

2.对于每次的询问,依次扫描k个点。对于集合中的u和v两点,每次我们求出u和v的LCA,计算u和v到LCA的距离,如果u和v到LCA的距离同时大于1,那么说明无法找到一条路径,使得u和v到该路径链的距离小于等于1。

3.对于k个点如何check?每次check完点u和点v到LCA的距离后,把到LCA距离最远的那个点作为分支链去和下一个要查询的结点进行对比,这样贪心下去一定是最优的。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 2e5+500;
 4 const int maxbit = 18;
 5 vector<int> g[maxn];
 6 int dep[maxn];
 7 int fa[maxn][maxbit];
 8 int Log[maxn];
 9 int n;
10 typedef long long ll;
11 void add(int u,int v){
12     g[u].push_back(v),g[v].push_back(u);
13 }
14 void pre(){
15     Log[0] = -1;
16     Log[1] = 0,Log[2] = 1;
17     for(int i = 3;i<maxn;i++) Log[i] = Log[i/2] + 1;
18 }
19 void dfs(int cur,int father){
20     dep[cur] = dep[father] + 1;
21     fa[cur][0] = father;
22     for(int j = 1;(1<<j)<=n;j++){
23         fa[cur][j] = fa[fa[cur][j-1]][j-1];
24     }
25     for(int i = 0;i<g[cur].size();i++){
26         if(g[cur][i]!=father){
27             dfs(g[cur][i],cur);
28         }
29     }
30 }
31 int LCA(int u,int v){
32     if(dep[u]<dep[v]) swap(u,v);
33     int dist = dep[u] - dep[v];
34     while(dep[u]!=dep[v]){
35         u = fa[u][Log[dep[u]-dep[v]]];
36     }
37     if(u == v) return u;
38     for(int i = Log[dep[u]];i>=0;i--){
39         if(fa[u][i]!=fa[v][i]){
40             u = fa[u][i];
41             v = fa[v][i];
42         }
43     }
44     return fa[u][0];
45 }
46 int main(){
47     int q;
48     scanf("%d%d",&n,&q);
49     for(int i = 1;i<n;i++){
50         int u,v;
51         scanf("%d%d",&u,&v);
52         add(u,v);
53     }
54     pre();
55     dfs(1,0);
56     while(q--){
57         int k;scanf("%d",&k);
58         bool f = 0;
59         int t[k+1] ;
60         for(int i = 1;i<=k;i++) scanf("%d",&t[i]);
61         int v = t[1];//当前对比点设为v
62         for(int i = 2;i<=k;i++){
63             int lca = LCA(v,t[i]);
64             if(abs(dep[t[i]]-dep[lca]) > 1&& abs(dep[v]-dep[lca])>1){
65                 f = 1;//如果出现到lca距离同时大于1,则一定无法找到树链满足题意
66                 break;
67             }
68             abs(dep[t[i]]-dep[lca])>abs(dep[v]-dep[lca])? v = t[i]:v = v;        //如果t[i]到lca的距离更远,则把v更新为t[i],贪心地与下一个点对比。    
69         }
70         if(!f) cout<<"YES"<<endl;
71         else cout<<"NO"<<endl;
72     }
73     return 0;
74 }
75 /*
76 8
77 13 13 9 12 13 1 13 1
78 */

 

Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

标签:break   return   contest   更新   处理   log   查询   namespace   wap   

原文地址:https://www.cnblogs.com/AaronChang/p/12590348.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!