HDU2586 How far away?(倍增LCA算法求带边权树上最短路)

题意:

勇气小镇是一个有着n个房屋的小镇,为什么把它叫做勇气小镇呢,这个故事就要从勇气小镇成立的那天说起了,
修建小镇的时候,为了让小镇有特色,镇长特地只修了n-1条路,并且规定说,所有在勇气小镇的村民,每一次出门必须规划好路线,
路线必须满足在到达终点之前绝对不走回头路。每个人都要这样,不然那个人就不配在小镇生活下去,因为他没有这个勇气。
事实上,这并不能算一项挑战,因为n-1条路已经连通了每户人家,不回头地从起点到终点,只是一个时间上的问题。
由于小镇上的福利特别好,所以小懒入住了这个小镇,他规划了m次的行程,每次从L房屋到R房屋,他想问你他每次从L房屋到R房屋最少能走多少路。

题解:

倍增LCA求树上最短路,这颗树是带边权的树,所以需要加一个数组。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1e5+10;
int head[maxn];
int tol;
int N,M;
struct node {
    int u;
    int v;
    int w;
    int next;
}edge[maxn];
void addedge (int u,int v,int w) {
    edge[tol].u=u;
    edge[tol].v=v;
    edge[tol].w=w;
    edge[tol].next=head[u];
    head[u]=tol++;
}

//lca
int father[20][maxn];
int h[maxn];
int d[maxn];
void dfs (int x) {
    for (int i=head[x];i!=-1;i=edge[i].next) {
        int v=edge[i].v;
        if (v==father[0][x]) continue;
        father[0][v]=x;
        h[v]=h[x]+1;
        d[v]=d[x]+edge[i].w;
        dfs(v);
    }
} 
int lca (int x,int y) {
    if (h[x]<h[y]) swap(x,y);
    for (int i=17;i>=0;i--) 
        if (h[x]-h[y]>>i) x=father[i][x];
    if (x==y) return x;
    for (int i=17;i>=0;i--) {
        if (father[i][x]!=father[i][y]) {
            x=father[i][x];
            y=father[i][y];
        }
    }
    return father[0][x];
}
int getDis (int x,int y) {
    return d[x]+d[y]-d[lca(x,y)]*2;
}
int main () {
    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d",&N,&M);
        memset(head,-1,sizeof(head));
        memset(father,0,sizeof(father));
        memset(h,0,sizeof(h));
        memset(d,0,sizeof(d));
        tol=0;
        for (int i=0;i<N-1;i++) {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dfs(1);
        for (int i=1;i<=17;i++) 
            for (int j=1;j<=N;j++)
                father[i][j]=father[i-1][father[i-1][j]];
        for (int i=0;i<M;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            printf("%d
",getDis(u,v));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zhanglichen/p/12526609.html