1#树上倍增

  以前写的博客:http://www.cnblogs.com/yyf0309/p/5972701.html

  预处理时间复杂度O(nlog2n),查询O(log2n),也不算难写。

2#st表(RMQ)

  首先对一棵树进行dfs,得到欧拉序列,记录下每个节点的第一次出现位置。

[算法整理]树上求LCA算法合集

  (先序遍历这棵树,访问到的节点(无论是从深的一层返回还是父节点访问)就加入到序列中,序列长度为2 * n - 1)

  根据欧拉序列神奇的特性,两个点第一次出现的位置之间,深度最小的一个点,是这两个点LCA(反正我是不会证明)。于是可以干什么呢?就建st表就行了。

  预处理时间复杂度O(2nlog2(2n) + n),查询时间复杂度O(log2n)。

codevs 商务旅行:

  1 /**
  2  * codevs
  3  * Problem#1036
  4  * Accepted
  5  * Time:52ms
  6  * Memory:2736k
  7  */
  8 #include<iostream>
  9 #include<sstream>
 10 #include<cstdio>
 11 #include<cmath>
 12 #include<cstdlib>
 13 #include<cstring>
 14 #include<cctype>
 15 #include<queue>
 16 #include<set>
 17 #include<map>
 18 #include<stack>
 19 #include<vector>
 20 #include<algorithm>
 21 #ifndef    WIN32
 22 #define    AUTO "%I64d"
 23 #else
 24 #define AUTO "%lld"
 25 #endif
 26 using namespace std;
 27 typedef bool boolean;
 28 #define smin(a, b) (a) = min((a), (b))
 29 #define smax(a, b) (a) = max((a), (b))
 30 template<typename T>
 31 inline void readInteger(T& u){
 32     char x;
 33     int aFlag = 1;
 34     while(!isdigit((x = getchar())) && x != '-');
 35     if(x == '-'){
 36         aFlag = -1;
 37         x = getchar();
 38     }
 39     for(u = x - '0'; isdigit((x = getchar())); u = u * 10 + x - '0');
 40     ungetc(x, stdin);
 41     u *= aFlag;
 42 }
 43 
 44 template<typename T>class Matrix{
 45     public:
 46         T *p;
 47         int lines;
 48         int rows;
 49         Matrix():p(NULL){    }
 50         Matrix(int rows, int lines):lines(lines), rows(rows){
 51             p = new T[(lines * rows)];
 52         }
 53         T* operator [](int pos){
 54             return (p + pos * lines);
 55         }
 56 };
 57 #define matset(m, i, s) memset((m).p, (i), (s) * (m).lines * (m).rows)
 58 
 59 ///map template starts
 60 typedef class Edge{
 61     public:
 62         int end;
 63         int next;
 64         Edge(const int end = 0, const int next = 0):end(end), next(next){}
 65 }Edge;
 66 typedef class MapManager{
 67     public:
 68         int ce;
 69         int *h;
 70         Edge *edge;
 71         MapManager(){}
 72         MapManager(int points, int limit):ce(0){
 73             h = new int[(const int)(points + 1)];
 74             edge = new Edge[(const int)(limit + 1)];
 75             memset(h, 0, sizeof(int) * (points + 1));
 76         }
 77         inline void addEdge(int from, int end){
 78             edge[++ce] = Edge(end, h[from]);
 79             h[from] = ce;
 80         }
 81         inline void addDoubleEdge(int from, int end){
 82             addEdge(from, end);
 83             addEdge(end, from);
 84         }
 85         Edge& operator[] (int pos) {
 86             return edge[pos];
 87         }
 88 }MapManager;
 89 #define m_begin(g, i) (g).h[(i)]
 90 ///map template ends
 91 
 92 int n, m;
 93 int cnt = 0;
 94 Matrix<int> st;
 95 int* seq;
 96 int *dep, *app;
 97 MapManager g;
 98 const int P = 15;
 99 int *mlog2;
100 
101 inline void init() {
102     readInteger(n);
103     g = MapManager(n, 2  * n);
104     seq = new int[(const int)(2 * n + 1)];
105     dep = new int[(const int)(n + 1)];
106     app = new int[(const int)(n + 1)];
107     for(int i = 1, a, b; i < n; i++){
108         readInteger(a);
109         readInteger(b);
110         g.addDoubleEdge(a, b);
111     }
112     dep[0] = 0;
113 }
114 
115 void dfs(int node, int f) {
116     seq[++cnt] = node;
117     dep[node] = dep[f] + 1;
118     app[node] = cnt;
119     for(int i = m_begin(g, node); i != 0; i = g[i].next) {
120         int& e = g[i].end;
121         if(e == f)    continue;
122         dfs(e, node);
123         seq[++cnt] = node;
124     }
125 }
126 
127 inline void init_log() {
128     mlog2 = new int[(const int)(2 * n + 1)];
129     mlog2[1] = 0;
130     for(int i = 2; i <= 2 * n; i++)
131         mlog2[i] = mlog2[i / 2] + 1; 
132 }
133 
134 inline void init_st() {
135     init_log();
136     st = Matrix<int>(cnt, mlog2[cnt] + 1);
137     for(int i = 1; i <= cnt; i++)
138         st[i][0] = seq[i];//,cout << i << " " << 0 << ":" << st[i][0] << endl;
139     for(int j = 1; j <= P; j++)
140         for(int i = 1; i + (1 << j) - 1 <= cnt; i++)
141             st[i][j] = (dep[st[i][j - 1]] < dep[st[i + (1 << (j - 1))][j - 1]]) ? (st[i][j - 1]) : (st[i + (1 << (j - 1))][j - 1]);
142 //            cout << i << " " << j << ":" << st[i][j] << endl;
143 }
144 
145 inline int lca(int a, int b) {
146     if(app[a] > app[b])    swap(a, b);
147     int pos = mlog2[app[b] - app[a] + 1];
148     int u = st[app[a]][pos];
149     int v = st[app[b] - (1 << pos) + 1][pos];
150     return (dep[u] > dep[v]) ? (v) : (u);
151 }
152 
153 int last;
154 int dist;
155 inline void solve() {
156     readInteger(m);
157     readInteger(last);
158     for(int i = 1, a; i < m; i++){
159         readInteger(a);
160         int l = lca(a, last);
161         dist += dep[a] + dep[last] - 2 * dep[l];
162         last = a;
163     }
164     printf("%d", dist);
165 }
166 
167 int main() {
168     init();
169     dfs(1, 0);
170     init_st();
171     solve();
172     return 0;
173 }
商务旅行(st表)

相关文章:

  • 2021-08-26
  • 2021-08-31
  • 2021-08-09
  • 2022-12-23
  • 2022-01-05
  • 2021-10-21
  • 2021-11-03
猜你喜欢
  • 2022-01-28
  • 2021-12-13
  • 2021-11-03
  • 2021-05-31
  • 2021-09-09
相关资源
相似解决方案