LCA
- LCA的定义:
方法1: 递归算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| struct Node{ int val; Node* left; Node* right; Node(int v):val(v),left(nullptr),right(nullptr){}; }
Node* LCA(Node* root, int u,int v){ if(root==nullptr){ return nullptr; } if(root->val == u || root->val == v){ return root; } Node* left = LCA(root->left,u,v); Node* right = LCA(root->right,u,v); if(left!=nullptr && right!=nullptr){ return root; }else if(left!=nullptr){ return left; }else if(right!=nullptr){ return right; }else{ return nullptr; } }
|
倍增寻找(ST算法)
算法执行之前,我们需要统计每个结点v的深度depth(v).
LCA的特点: 如果结点w是结点u和结点v的最近公共祖先的话:
让u往上走(depth(w) - depth(u) )步, 让v往上走(depth(v) - depth(w) )步,u,v都将走到结点w
寻找结点u和结点v LCA的 倍增算法的基本思路:
结点w未知,我们首先让u和v中较深的点往上走|depth(u)-depth(v)|步,再一起往上走.
并且利用二分搜索求出可到达的最近公共祖先的最小步数.
不过其中要维护一个father数组 , 并且father[i][j]
表示 结点i 往上走j-1 步得到的祖先结点,father[]
[源码]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
#include<iostream> #include<vector> #include <cmath>
using namespace std; const int MAX = 1000; int father[MAX][MAX]; int depth[MAX]; int N ; vector<int> tree[MAX] ;
void dfs(int cur,int pre,int d){ father[cur][0] = pre; depth[cur] = d; if(tree[cur].empty()){ return; } int size = tree[cur].size(); for(int i=0;i<size;i++){ int ch =tree[cur][i]; if(ch!=pre){ dfs(ch,cur,d+1); } } }
void init(int root){ dfs(root,-1,0); for(int j=0;(1<<(j+1))<N;j++){ for(int i= 0;i<N;i++){ if(father[i][j]<0) father[i][j+1] = -1; else father[i][j+1] = father[father[i][j]][j]; }
} }
int LCA(int u,int v){ if(depth[u]>depth[v]){ swap(u,v); } int temp = depth[v] - depth[u];
v = father[v][temp-1]; if(v==u){ return u; } for( int i=(int)log2(N*1.0);i>=0;i--){ if(father[u][i]!= father[v][i]){ u = father[u][i]; v = father[v][i]; } } return father[u][0]; }
int main(){ N =8; for(int i=1;i<=N;i++){ int m=0; cin>>m; for(int j=0;j<m;j++){ int temp; cin>>temp; tree[i].push_back(temp); } } init(5); cout<<LCA(3,2); }
|