POJ 1330 Nearest Common Ancestors 最近公共祖先

Posted xxfy1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1330 Nearest Common Ancestors 最近公共祖先相关的知识,希望对你有一定的参考价值。

LCA模板题,用倍增法去写
首先把每一个节点的向上(2^i (i in mathbb N))个祖先给枚举出来
再把要求公共祖先的两个节点拉到同一深度
向上不断利用倍增一起跳跃同样层数到他们各自的非公共祖先的祖先节点
最后他们一起到达共同祖先节点的子节点,再同时向上走一位即可
在这个过程中,同时维护cost即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;

const int N = 40001;
int p[N][31], cost[N][31], lv[N];
vector<pii> G[N];

int dfs(int x,int fx) {
    p[x][0]=fx;
    lv[x]=lv[fx]+1;
    for(int i=1;i<31;i++) {
        p[x][i]=p[p[x][i-1]][i-1];
        cost[x][i]=cost[p[x][i-1]][i-1]+cost[x][i-1];
    }
    for(auto u:G[x]){
        if(u.first==fx) continue;
        cost[u.first][0]=u.second;
        dfs(u.first,x);
    }
}

int lca(int x,int y) {
    if(lv[x]>lv[y]) swap(x,y);
    int tmp = lv[y]-lv[x], ans = 0;
    for(int i=0;tmp;i++,tmp>>=1)
        if(tmp&1) ans += cost[y][i],y=p[y][i];
    if(y==x) return ans;
    for(int i=30;i>=0&&y!=x;i--) {
        if(p[x][i]==p[y][i]) continue;
        ans+=cost[x][i]+cost[y][i];
        x=p[x][i];
        y=p[y][i];
    }
    ans+=cost[x][0]+cost[y][0];
    return ans;
}

int n,m,a,b,c;

int solve(){
    for(int i=0;i<N;i++) G[i].clear();
    cin>>n>>m;
    for(int i=1;i<n;i++) {
        cin>>a>>b>>c;
        G[a].push_back(make_pair(b,c));
        G[b].push_back(make_pair(a,c));
    }
    dfs(1,0);
    while(m--){
        cin>>a>>b;
        cout<<lca(a,b)<<endl;
    }
}

int main(){
    int t;
    cin>>t;
    while(t--) solve();
}

以上是关于POJ 1330 Nearest Common Ancestors 最近公共祖先的主要内容,如果未能解决你的问题,请参考以下文章

poj1330 Nearest Common Ancestors

[POJ1330]Nearest Common Ancestors(LCA, 离线tarjan)

POJ 1330 Nearest Common AncestorsLCA Tarjan算法

POJ 1330 Nearest Common Ancestors (最近公共祖先LCA + 详解博客)

POJ1330Nearest Common Ancestors

POJ 1330 Nearest Common Ancestors(lca)