1 #include <iostream>
2 #include <vector>
3 #include <algorithm>
4 #define MAXN 100
5 //2^MAXLOG2>=最大深度
6 #define MAXLOG2 7
7 using namespace std;
8
9 vector<int>G[MAXN];
10 int depth[MAXN];
11 int ancestor[MAXN][MAXLOG2];
12
13 void creat()//输入并存储树
14 {
15 int n,x,y;
16 cin>>n;//n条边
17 for(int i=0;i<n;i++)
18 {
19 cin>>x>>y;
20 G[x].push_back(y);
21 G[y].push_back(x);
22 }
23 }
24 void dfs(int x,int father)
25 {
26 depth[x]=depth[father]+1;//计算x深度
27 ancestor[x][0]=father;
28 //计算x结点的2^i步祖先
29 for(int i=1;i<MAXLOG2;i++)
30 //因为是dfs,所以深度小的结点的ancestor总会先算出来
31 //MAXLOG2太大了会怎样?因为ancestor[0][i]=0,所以不管怎样往上走都是0
32 ancestor[x][i]=ancestor[ancestor[x][i-1]][i-1];
33 for(int i=0;i<G[x].size();i++)
34 if(G[x][i]!=father)dfs(G[x][i],x);
35 }
36 int lca(int x,int y)
37 {
38 if(depth[x]<depth[y])swap(x,y);
39 /*假设x与y深度相差z,x每次走2^i(i从最大每次循环减少1)步总能到达y的深度
40 证明:将z转换成二进制,再转换成十进制
41 则肯定等于2^i1 + 2^i2 + 2^i3 ... 形式 */
42 for(int i=MAXLOG2-1;i>=0;i--)
43 //如何防止走多了?走完后的深度比y还小,说明走多了,这时候我们就不走
44 if(depth[ancestor[x][i]]>=depth[y])x=ancestor[x][i];
45 if(x==y)return x;
46 //假设x与LCA相距L步,那么x,y都走L-1步仍然不相等,下面的循环是让x,y走L-1步
47 for(int i=MAXLOG2-1;i>=0;i--)
48 /*如何防止走多了?
49 注意循环结束条件,并非当x,y走完后相等
50 如果以x,y相等为结束条件,则有可能会走过了
51 此循环的目的是为了让x,y走L-1步
52 LCA相当于x,y的中点
53 为什么一定刚好走L-1步?
54 首先能确定的是存在两个结点再往上一步就是LCA
55 此循环让x,y只要不相等就往上走,x,y肯定会到达这两个结点
56 即x,y走L-1步会到达那两个结点。自己可以画图试试*/
57 if(ancestor[x][i]!=ancestor[y][i])
58 {
59 x=ancestor[x][i];
60 y=ancestor[y][i];
61 }
62 return ancestor[x][0]; //即x再向上走1(2^0)步即是LCA
63 }
64 int main()
65 {
66 creat();//数据要输入
67 dfs(1,0);
68 //cout<<lca(7,6);
69 return 0;
70 }