LCA模板

预处理之后 求树上两个点的祖先节点

模板一(不带距离查询只查询LCA)

typedef pair<int,int> P;
vector<int> g[maxn], sp;
int dep[maxn], dfn[maxn], lg[2*maxn];
P dp[21][2*maxn];

void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    dfn[u]=sp.size();
    sp.pb(u);
    for(auto v: g[u]){
        if(v==fa)continue;
        dfs(v,u);
        sp.pb(u);
    }
}
void lca_init(){
    int n=SZ(sp);
    for (int i = 1, j = 0; i <= n; i += 1){
        if(i == (1 << (j+1))) j++;
        lg[i] = j;
    }
    for (int i = 0; i < n; i += 1)
        dp[0][i] = {dfn[sp[i]], sp[i]};

    for (int j = 1; (1 << j) <= n; j += 1)
        for (int i = 0; i + (1 << j) - 1 < n; i += 1)
            dp[j][i] = min(dp[j-1][i], dp[j-1][i+(1<<(j-1))]);
}
int lca(int u,int v){
    int l = dfn[u], r = dfn[v];
    if(l > r)swap(l , r);
    int j = lg[r - l + 1];
    return min(dp[j][l], dp[j][r - (1<<j) + 1]).se;
}

// 调用示范:
dfs(1, 0);
lca_init();
printf("%d", lca(1, 2));

//注意: 多组输入记得清空图的vector

模板二(预处理查询树上两点间距离)

int dep[maxn], dist[maxn], fa[maxn][20];
void DFS(int u, int _dist, int _dep, int _fa) {
    dist[u] = _dist; dep[u] = _dep; fa[u][0] = _fa;
    for(int i = 0; i < SZ(g[u]); i++) {
        int to = g[u][i].fi, w = g[u][i].se;
        if(to == u || to == _fa) continue;
        DFS(to, _dist + w, _dep + 1, u);
    }
}
void presolve() {
    clr(fa, -1);
    for (int i = 1; i <= n; i++) {
        if(fa[i][0] == -1) DFS(i, 0, 0, i);
    }

    for(int i = 1; i < 20; i++) {
        for(int j = 1; j <= n; j++) {
            fa[j][i] = fa[fa[j][i - 1]][i - 1];
        }
    }
}
int LCA(int u, int v) {
    while(dep[u] != dep[v]) {
        if(dep[u] < dep[v]) swap(u, v);
        int d = dep[u] - dep[v];
        for(int i = 0; i < 20; i++) {
            if(d >> i & 1) u = fa[u][i];
        }
    }
    if(u == v) return u;
    for(int i = 20 - 1; i >= 0; i--) {
        if(fa[u][i] != fa[v][i]) {
            u = fa[u][i];
            v = fa[v][i];
        }
    }
    return fa[u][0];
}
int query(int u, int v) {
    return dist[u] + dist[v] - dist[LCA(u, v)] * 2;
}

//调用:
presolve();
//注意: 这个模板可以处理多棵不连通树的情况

results matching ""

    No results matching ""