可用倍增LCA解题

http://codevs.cn/problem/2370/

#include<bits/stdc++.h>
using namespace std;
const int M=5e4+5;
const int N=20;
struct node{
    int v,w;
    node(int vv=0,int ww=0):v(vv),w(ww){}
};
vector<node>e[M];
int n,grand[M][N],dis[M][N],deep[M],book[M],root,s;
void dfs(int u){
    for(int i=1;i<=s;i++){
        grand[u][i]=grand[grand[u][i-1]][i-1];
        dis[u][i]=dis[u][i-1]+dis[grand[u][i-1]][i-1];
        if(!grand[u][i])
            break;
    }
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i].v;
        if(v!=grand[u][0]){
            grand[v][0]=u;
            deep[v]=deep[u]+1;
            dis[v][0]=e[u][i].w;
            dfs(v);
        }
    }
}
void init(){
    s=floor(log(1.0*n)/log(2.0));
    deep[0]=-1;
    dfs(root);
}
int LCA(int a,int b){
    if(deep[a]>deep[b])
        swap(a,b);
    int ans=0;
    for(int i=s;i>=0;i--){
        if(deep[a]<deep[b]&&deep[a]<=deep[grand[b][i]])
            ans+=dis[b][i],b=grand[b][i];
    }
    for(int i=s;i>=0;i--){
        if(grand[a][i]!=grand[b][i])
            ans+=dis[a][i],ans+=dis[b][i],a=grand[a][i],b=grand[b][i];
    }
    if(a!=b)
        ans+=dis[a][0]+dis[b][0];
    return ans;
}
int main(){

    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        u++;
        v++;///fu
        book[u]=1;
        e[u].push_back(node(v,w));
        e[v].push_back(node(u,w));
    }
    for(int i=1;i<=n;i++){
        if(!book[i]){
            root=i;
            break;
        }
    }
    init();
    int m;
    scanf("%d",&m);
    while(m--){
        int u,v;
        scanf("%d%d",&u,&v);
        u++,v++;
        printf("%d\n",LCA(u,v));
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/starve/p/11200925.html