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 " , 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 " , 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号节点为根)