zoukankan      html  css  js  c++  java
  • Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

    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 */
  • 相关阅读:
    [转]我们应该做什么样的研究
    [转]面向服务架构(SOA)和企业服务总线(ESB)
    [转]程序员应知——团队精神
    vs2010 调试快捷键
    asp.net 获取ip的6种方法
    解决了防止用户重复登陆和session超时
    IE 10 也能随网站应变,图标决定一切!
    Sony VAIO Duo 11 游戏性能测试
    翻出Windows 8 当中的游戏管理器
    Office 2013预览版已到期,需要付费才可正常使用
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12590348.html
Copyright © 2011-2022 走看看