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. ThreadLocal的使用场景
  2. python初学火车座位判断_Python学习第三课 判断(if)语句
  3. Spark编程指引(四)----共享变量(广播变量和累加器)
  4. python文件打开模式中、使用w模式、文件指针指向_被python文件模式“w+”所迷惑
  5. 最美数学公式的150年:麦克斯韦方程组与“无用”的科学
  6. Java volatile关键字
  7. 递推+高精度——蜜蜂路线(洛谷 P2437)
  8. heka 输出到mysql_用php与mysql的电子贺卡程序
  9. 【定位问题】基于matlab RSSI和模拟退火优化粒子群算法求解无线传感器网络定位问题【含Matlab源码 1766期】
  10. 硕士研究生毕业论文书写格式总结
  11. Linux串口驱动加载过程
  12. 上银驱动器使用手册_禾川伺服驱动器说明书
  13. 2022年危险化学品经营单位安全管理人员找解析及危险化学品经营单位安全管理人员复审考试
  14. mysql awr报告生成_批量生成AWR报告(转载总结)
  15. VSCode使用Vim插件心得
  16. selenium入门详细指南(附淘宝抢购案例)
  17. 17-[案例1]奇虎导航案例
  18. Kuma初步学习笔记-universal 模式
  19. 论文阅读-Boosting Data-driven Evolutionary Algorithm with Localized Data Generation
  20. Powershell之MOF后门

热门文章

  1. 平衡二叉树平衡因子怎么计算_数据结构PHP 平衡二叉树(AVL)的平衡原理
  2. [8] ADB 查看日志
  3. python3纵向输出字符串_笔记||Python3之字符串格式化输出
  4. echarts x轴像直尺一样设置刻度_MATLAB作图实例:6:指定轴刻度值和标签
  5. Spring Boot笔记-logback-spring.xml获取application.properties中的变量
  6. Java中java.lang.Class的初步学习
  7. Qt文档阅读笔记-QVariant::value()与qvariant_cast解析及使用
  8. Qt creator5.7 OpenCV249之高斯滤波(含源码下载)
  9. c语言缓冲池管理算法,操作系统复习资料
  10. oracle脚本导入mysql数据库_oracle脚本导入mysql数据库