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;
}

 

posted @ 2021-07-23 11:06  wateriness  阅读(55)  评论(0)    收藏  举报