dfs序是指你用dfs遍历一棵树时,每个节点会按照遍历到的先后顺序得到一个序号。然后你用这些序号,可以把整个遍历过程表示出来。

如上图所示,则整个遍历过程为1 2 3 2 4 5 4 6 4 2 1 7 8 7 1

反正按照实现目的不同,dfs序会长得不太一样,比如说为了实现LCA就需要上面形式的dfs序。

用vs[]来保存整个遍历过程。

id[i]用来保存i节点的序号第一次出现在vs[]中时的下标。

这样当询问u,v点的LCA是谁是,你只要找到在vs[id[u]<= i <= id[v]]中最小值即可,那个最小值所对应的节点就是u,v的LCA

而这个过程你可以用RMQ进行预处理,然后O(1)就可以得到。(你应该知道vs[]的总长度为n*2-1)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int M = 1e5 + 10 ;
 4 vector<int> g[M] ;
 5 int n ;
 6
 7 vector<int> vs ;//dfs order
 8 int tot ;
 9 int orm[M] ;
10 int id[M] ;
11 int dep[M] ;
12
13 int d[M][30] ;//RMQ
14 void dfs (int o , int u ,int  DEP) {
15         int tmp = tot ++ ;
16         dep[u] = DEP ;
17         id[u] = vs.size () ;
18         orm[tmp] = u ;
19         vs.push_back (tmp) ;
20
21         for (int i = 0 ; i < g[u].size () ; i ++) {
22                 int v = g[u][i] ;
23                 if (v == o) continue ;
24                 dfs (u , v , DEP + 1) ;
25         }
26         int len = vs.size () ;
27         if (vs[len-1] == tmp) vs.push_back (vs[id[o]]) ;
28         else vs.push_back (tmp) ;
29 }
30
31 void init_RMQ () {
32         for (int i = 0 ; i < 2*n-1 ; i ++) d[i][0] = vs[i] ;
33         for (int j = 1 ; (1 << j) <= n ; j ++) {
34                 for (int i = 0 ; i + (1 << j) <= n ; i ++) {
35                         d[i][j] = min (d[i][j-1] , d[i+(1<<(j-1))][j-1]) ;
36                 }
37         }
38 }
39
40 int RMQ (int l , int r) {
41         printf ("l = %d , r = %d\n" , l , r ) ;
42         int k = 0 ;
43         while ( (1<<(k+1)) <= r - l + 1) k ++ ;
44         int tmp = min (d[l][k] , d[1+r-(1<<k)][k]) ;
45         return orm[tmp] ;
46 }
47 void Print () {
48         for (int i = 0 ; i < 2*n-1 ; i ++) printf ("%3d " , i ) ; puts ("") ;
49         puts ("dfs order:") ;
50         for (int i = 0 ; i < 2*n-1 ; i ++) printf ("%3d " , vs[i]) ; puts ("") ;
51         puts ("deep:") ;
52         for (int i = 0 ; i < n ; i ++) printf ("%3d " , dep[i]) ; puts ("") ;
53         puts ("id :") ;
54         for (int i = 0 ; i < n ; i ++) printf ("%3d " , id[i]) ; puts ("") ;
55 }
56
57 void LCA () {
58         dfs (0,0,0) ;
59         init_RMQ () ;
60         Print () ;
61 }
62
63 int main () {
64         cin >> n ;
65         for (int i = 0 ; i < n - 1 ; i ++) {
66                int u , v ;
67                cin >> u >> v ;
68                g[u].push_back (v) ;
69                g[v].push_back (u) ;
70         }
71         LCA () ;
72         int Q ;
73         cin >> Q ;
74         while (Q --) {
75                 int u , v ;
76                 cin >> u >> v ;
77                 if (id[u] > id[v]) swap (u , v ) ;
78                 int ans = RMQ (id[u] , id[v]) ;
79                 printf ("The %d and %d the lastest ans is %d , and they are away from %d\n" , u , v , ans , dep[u]+dep[v]-2*dep[ans]) ;
80         }
81         return 0 ;
82 }

测试数据:

8
0 1
0 2
1 3
1 4
2 5
4 6
4 7
3
0 4
3 4
6 2

3次询问的答案你画一下即可。hhhhhh(以0号节点为根)

转载于:https://www.cnblogs.com/get-an-AC-everyday/p/4673255.html

dfs序 + RMQ = LCA相关推荐

  1. A and B and Lecture Rooms CodeForces - 519E LCA+dfs序

    看到这个题的第一个思路就是就是统计以每一个点为根的所有节点个数,然后具体就分情况讨论一下即可. 因为刚刚学习了dfs序,这个题就用了dfs序来通过进出时间戳来相减表示其为根的子节点个数. 分情况 我们 ...

  2. POJ - 2763 Housewife Wind LCA+dfs序+线段树

    q次询问求两个点之间的距离,并且可以随时修改某条边的长度,最短距离可以用lca来求,但是树上维护每一个点到root的距离必须要用dfs序来记录时间戳,在dfs的时候顺便记录每一条边(u,v)对应的v节 ...

  3. LCA ---- E. Tree Queries[LCA或者dfs序的解法]

    题目链接 题目大意:就是给你一颗树,然后qqq次询问每次询问会给出kkk个点,要求你判断一下这些点是否在存在一条从1到某个点u的链使得这k个点都在这条链上或者距离这条链距离为1的位置上 解法1:dfs ...

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

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

  5. Innumerable Ancestors 尺取 dfs序 lca

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

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

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

  7. CodeForces - 1328E Tree Queries(dfs序/LCA)

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

  8. HDU - 6203 ping ping ping(LCA+dfs序+线段树)

    题目链接:点击查看 题目大意:给出一棵由n+1个节点组成的数,节点编号为0~n(这个无关紧要,预处理时所有节点以及n都自增1即可转换为正常的模型了),现在给出m组节点u和v,问若想让m组u和v都断开连 ...

  9. codeforces E. Jamie and Tree LCA+dfs序+线段树

    题解: 写起来还稍微有点麻烦. dfs序+线段树可以维护子树的整体修改和查询. 因此,这道题我们要往子树上靠. 我们首先从1号点进行dfs遍历,顺便求出点的dfs序和深度,然后我们采用倍增的思想,可以 ...

最新文章

  1. 面试官:哥们,你们的系统架构中为什么要引入消息中间件?
  2. Java基础知识强化之集合框架笔记76:ConcurrentHashMap之 ConcurrentHashMap简介
  3. python 文件处理1:将某一目录下的文件合并
  4. Unity-2017.2官方实例教程Roll-a-ball(一)
  5. 常用的函数式接口_Predicate接口_默认方法ornegate
  6. SQL重复记录查询的几种方法
  7. 关于高级导数的一个不等式估计
  8. 错误: 找不到或无法加载主类 helloworld_全面剖析虚拟机类加载机制
  9. 部署egg需要用到pm2吗_使用宝塔面板部署校园综合服务平台项目
  10. 2.python中的矩阵、多维数组----numpy
  11. python的解释器spython介绍
  12. idea的tomcat实现热部署遇到的问题
  13. Eclipse使用问题
  14. springBoot的学习整理 摘抄蚂蚁课堂
  15. 通过qq进行ip定位
  16. tomcat6到tomcat9解压版(64位)随意下载
  17. 51单片机存储器结构
  18. iis部署网站 html文件路径,iis发布网页
  19. android 7.0读写 sdcard,Android 学习笔记之SDCard读写
  20. Win7系统网络适配器不见了的解决办法

热门文章

  1. ThinkPHP6项目基操(10.不可预知的內部异常处理)
  2. matlab 多 带阻,matlab程序之——滤波器(带通-带阻
  3. PHPJavaScript笔记-后端利用Refresh头带错误信息给前端(野路子操作)
  4. Qt笔记-使用正则表达式匹配URL及获取Get请求后面的参数(QRegExp)
  5. Java基础入门笔记-链表与容器
  6. 7.2图的存储结构(十字链表、邻接多重表、边集数组)
  7. java web认证考试_用Java实现Web服务器HTTP协议
  8. java writedouble_Java FSDataOutputStream.writeDouble方法代碼示例
  9. git 历史操作日志_Git - 查看提交历史
  10. python xposed_GitHub - twqdev/CPWechatXposed: 使用Xposed Hook微信等APP