LCA
一般作为解题的一个工具来使用。
意思就是最近公共祖先,所以是需要指定根的。
算法有离线tarjan和在线倍增(当然是选择倍增啦!)
由于刚学了ST表,再来学习这个就觉得十分的容易。
fa[i][j]表示i节点的第1<<j辈的父亲。
查找时首先把x和y调到同一deep,然后再从大往小跳。
反正就是那个东西,看代码,看代码。(md表示max deep)
P3379 模板题
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 const int N = 500010; 5 struct Edge 6 { 7 int u,v,next; 8 }edge[N<<1];int top; 9 int point[N],fa[N][30],deep[N],md,n; 10 inline void add(int x,int y) 11 { 12 top++; 13 edge[top].u=x; 14 edge[top].v=y; 15 edge[top].next=point[x]; 16 point[x]=top; 17 return; 18 } 19 void dfs(int op,int d) 20 { 21 deep[op]=d; 22 int ed,i=point[op]; 23 while(i) 24 { 25 ed=edge[i].v; 26 if(deep[ed]) fa[op][0]=ed; 27 else dfs(ed,d+1); 28 i=edge[i].next; 29 } 30 return; 31 } 32 void pre_lca() 33 { 34 for(int j=1;j<=md;j++) 35 { 36 for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; 37 } 38 return; 39 } 40 int lca(int x,int y) 41 { 42 if(deep[x]>deep[y]) swap(x,y); 43 for(int i=md;i>=0;i--) 44 { 45 if(deep[fa[y][i]]>deep[x]) y=fa[y][i]; 46 else if(deep[fa[y][i]]==deep[x]){y=fa[y][i];break;} 47 } 48 if(deep[x]!=deep[y]) y=fa[y][0];///this!!!!!!! 49 if(x==y) return x; 50 for(int i=md;i>=0;i--) 51 { 52 if(fa[x][i]!=fa[y][i]) {x=fa[x][i];y=fa[y][i];} 53 } 54 return x==y?x:fa[x][0]; 55 } 56 int main() 57 { 58 int m,r; 59 scanf("%d%d%d",&n,&m,&r); 60 while((1<<md)<=n) md++;///this! 61 md--; 62 int x,y; 63 for(int i=1;i<n;i++) 64 { 65 scanf("%d%d",&x,&y); 66 add(x,y); 67 add(y,x); 68 } 69 dfs(r,1); 70 pre_lca(); 71 while(m--) 72 { 73 scanf("%d%d",&x,&y); 74 printf("%d\n",lca(x,y)); 75 } 76 77 return 0; 78 }