题目链接:点击查看

题目大意:给出一棵以点 1 为根节点的树,接下来有 m 次询问,每次询问给出 k 个点,题目问我们能否找到一个点 u ,使得从根节点到点 u 的简单路径,到 k 个点的每个点的距离都小于等于 1

题目分析:我的第一反应是用lca,仿照bfs那样,逐层询问每两个点之间的lca,但是不太会操作,队友和我说可以随便找一条最长的链然后检查,不过复杂度顶不住,赛后补题的时候,想到了可以用dfs序优化,这样总的时间复杂度就下降到了O( n )了

具体做法就是预处理出树上的dfs序,以及每个节点的深度,对于每次需要询问的 k 个点,我们找到深度最深的那个点作为点 u ,因为dfs序主要是负责检查某个点是否在子树中的,所以只要这个最深的点 u 都位于这 k 个点,或者这些点父节点的子树中,就说明肯定可以找到一条满足条件的树链

2020.3.27更新:

补一下lca的做法,仍然是选择深度最深的结点作为点 u ,对于 k 个点,每个点都与点 u 求一下 lca ,如果想要满足题目中的距离限制,就要使得每个lca不是其本身,就是其父节点,时间复杂度为nlogn

代码:

dfs序:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;vector<int>node[N];int fa[N],in[N],out[N],deep[N],cnt;int k,max_deep,a[N];void dfs(int u,int f,int dep)
{fa[u]=f;deep[u]=dep;in[u]=++cnt;for(auto v:node[u]){if(v==f)continue;dfs(v,u,dep+1);}out[u]=cnt;
}bool check(int a,int b)
{return in[a]<=in[b]&&out[b]<=out[a];
}bool solve()
{for(int i=1;i<=k;i++){if(!check(a[i],max_deep)&&!check(fa[a[i]],max_deep))return false;}return true;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}dfs(1,-1,0);while(m--){scanf("%d",&k);max_deep=0;for(int i=1;i<=k;i++){scanf("%d",a+i);if(max_deep==0||deep[max_deep]<deep[a[i]])max_deep=a[i];}if(solve())puts("YES");elseputs("NO");}return 0;
}

LCA:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=2e5+100;vector<int>node[N];int deep[N],dp[N][20],limit;int a[N],max_deep,k; void dfs(int u,int fa,int dep)
{deep[u]=dep;dp[u][0]=fa;for(int i=1;i<=limit;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(auto v:node[u]){if(v!=fa)dfs(v,u,dep+1);}
}int LCA(int x,int y)
{if(deep[x]<deep[y])swap(x,y);for(int i=limit;i>=0;i--)if(deep[x]-deep[y]>=(1<<i))x=dp[x][i];if(x==y)return x;for(int i=limit;i>=0;i--)if(dp[x][i]!=dp[y][i]){x=dp[x][i];y=dp[y][i];}return dp[x][0];
}bool solve()
{for(int i=1;i<=k;i++){int lca=LCA(a[i],max_deep);if(lca!=a[i]&&lca!=dp[a[i]][0])return false;}return true;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);limit=log2(n)+1;for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}dfs(1,0,0);while(m--){scanf("%d",&k);max_deep=0;for(int i=1;i<=k;i++){scanf("%d",a+i);if(max_deep==0||deep[max_deep]<deep[a[i]])max_deep=a[i];}if(solve())puts("YES");elseputs("NO");}return 0;
}

CodeForces - 1328E Tree Queries(dfs序/LCA)相关推荐

  1. BZOJ2588 Count on a tree DFS序+LCA+值域主席树

    Count on a tree 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答 ...

  2. CF-825 G.Tree Queries(DFS)

    CF-825 G.Tree Queries(DFS) 题目链接 题意 一棵树nnn个节点(初始为白色),两种操作: 1 xxx 把节点xxx设置为黑色 2 xxx 求节点xxx到任意一个黑色节点的简单 ...

  3. Codeforces 375D - Tree and Queries(dfs序+莫队)

    题目链接:http://codeforces.com/contest/351/problem/D 题目大意:n个数,col[i]对应第i个数的颜色,并给你他们之间的树形关系(以1为根),有m次询问,每 ...

  4. Codeforces Round #316 (Div. 2) D. Tree Requests dfs序

    题目链接: 题目 D. Tree Requests time limit per test:2 seconds memory limit per test:256 megabytes 问题描述 Rom ...

  5. 牛客 - Colorful Tree(dfs序+LCA)

    题目链接:点击查看 题目大意:给出一棵 n 个节点构成的数,每个节点都有一个颜色,现在需要执行 m 次操作,每次操作分为如下两种类型: Q x:回答所有颜色为 x 的节点构成的连通子图含有的最少边数 ...

  6. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  7. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  8. Innumerable Ancestors 尺取 dfs序 lca

    给一棵树,m次查询,每次查询给两个集合,从这两个集合中分别选一个结点,使得这两个结点的lca的深度最大 考虑dfs序为3, 4, 5的三个结点,3和4的lca深度一定大于等于3和5的lca深度 所以可 ...

  9. 【POJ - 3321】 Apple Tree(dfs序 + 线段树维护 或 dfs序 + 树状数组维护)

    题干: There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the t ...

最新文章

  1. 2017西南计算机数学基础,[0838]《计算机数学基础》西南大学 2017 秋学期 计算机专业 作业题目及参考答案资料讲解.docx...
  2. SpringMvc接收日期参数
  3. python漏洞检测脚本_URL重定向漏洞,python打造URL重定向漏洞检测脚本
  4. 本地 服务器 文件传输,本地服务器文件传输
  5. Python计算序列中数字最大差值(美团2016校招笔试题)
  6. vue计算属性与监听器的区别
  7. 《学习opencv》笔记——关于一些画图的函数
  8. 直接下载Google Play上APP的安装包
  9. Java 按照拼音排序方法
  10. c语言中波浪线scanf,~scanf 波浪线
  11. Flash桌球游戏开发
  12. VS+Qt应用开发-设置软件图标
  13. DOS定时关机命令 windowXp
  14. java 保龄球游戏开发_2019-11-08-基于TDD实现的java版本的保龄球规则(实体类)
  15. voxsrc20_std_00-How many kinds of topology used in speaker recognition?
  16. Internet Download Manager v6.41.3中文特别版IDM下载器免费下载
  17. Ubuntu下,Kdevelop的简单使用与调试
  18. 数据挖掘算法原理与实践:数据预处理
  19. 网络舆情相关书籍推荐
  20. Henry前端笔记之 CSS相关

热门文章

  1. Lua语法入门HelloWorld
  2. JAVA中限制接口流量、并发的方法
  3. SpringMVC核心流程图
  4. zookeeper的名词复盘-数据模型
  5. mybatis注解开发使用二级缓存
  6. SpringBoot_配置-@ConfigurationProperties与@Value区别
  7. 抽屉效果_宜家靠边,好用不贵的全格收纳抽屉使用感受
  8. linux拷贝文件到多个目录,怎么在 Linux 中复制文件到多个目录中
  9. mysql自定义函数应用_mysql functions实例:在自定义函数中应用字符串函数
  10. python解压打开文件过多_自动解压大量压缩文件 Python 脚本 | 学步园