B - pog loves szh III
题目:

思路:
给定一个1为根的树,求了L,R的LCA
利用bfs求各节点的深度,求L,R的最近公共祖先
利用倍增的方法把LR的深度升到同一级再共同向上寻找共同祖先
代码实现:
#include <iostream> #include <cstring> #include <stdio.h> #include <queue> using namespace std; int n, q, ecnt; const int maxn = 300005; struct edge{//定义结构体存储边 int v, next; }e[maxn << 1]; int dep[maxn], f[20][maxn], head[maxn]; void bfs(int rt)//bfs预处理,记录个点的深度 { queue<int> q; q.push(rt); f[0][rt] = rt; dep[rt] = 0; while(!q.empty()){ int tmp = q.front(); q.pop(); for(int i = 1; i < 20; i++){ f[i][tmp] = f[i - 1][f[i - 1][tmp]]; } for(int i = head[tmp]; i != -1; i = e[i].next){ int v = e[i].v; if(v == f[0][tmp]) continue; dep[v] = dep[tmp] + 1; f[0][v] = tmp; q.push(v); } } } int LCA(int u, int v)//求LR的最近公共先祖 { if(dep[u] > dep[v]) swap(u, v);//如果前大于后交换 int hu = dep[u], hv = dep[v]; int tu = u, tv = v; for(int det = hv - hu, i = 0; det; det >>= 1, i++){ if(det & 1){ tv = f[i][tv]; } } if(tu == tv){ return tu; } for(int i = 19; i >= 0; i--){ if(f[i][tu] == f[i][tv]){ continue; } tu = f[i][tu]; tv = f[i][tv]; } return f[0][tu]; } void init()//清零初始化 { memset(head, -1, sizeof(head)); ecnt = 0; } void adde(int u, int v)//添加边 { e[ecnt].v = v; e[ecnt].next = head[u]; head[u] = ecnt++; } int dp[maxn][20]; int main() { while(scanf("%d", &n) != EOF){ init(); for(int i = 1; i < n; i++){ int x, y; scanf("%d%d", &x, &y); adde(x, y); adde(y, x); } bfs(1); scanf("%d", &q); while(q--){ int l, r; scanf("%d%d", &l, &r); cout<<LCA(l,r)<<endl; } } return 0; }

浙公网安备 33010602011771号