hdu 2586 How far away ?(LCA模板题)

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.

InputFirst line is a single integer T(T<=10), indicating the number of test cases. 
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n. 
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.OutputFor each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.Sample Input

2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

Sample Output

10
25
100
100

给你一棵树,树上的边有权值,问你连点之间距离多少?LCA的模板题,试一下模板,顺带加深理解。
dis(a,b)=dis(a,根)+dis(b,根)-2*dis( lca(a,b) , 根)
#include <bits/stdc++.h>

using namespace std;
const int maxn=44000;
int t,n,q;
int dis[maxn],dep[maxn],que[maxn];
int p[maxn];
bool vis[maxn];
int fa[maxn][50];
struct node
{
    int to,dis;
    node(int t,int d):to(t),dis(d){}
};
vector <node> e[maxn];
void init ()
{
    for (int i=0;i<n;++i)
        e[i].clear();
    memset(dis,0,sizeof dis);
    memset(dep,0,sizeof dep);
    memset(que,0,sizeof que);
}
void bfs (int x)
{
    memset(vis,false,sizeof vis);
    int w=1,r=1;
    que[1]=x;
    dep[x]=0;
    dis[x]=0;
    p[x]=-1;
    vis[x]=true;
    while (w<=r){
        int u=que[w];w++;
        for (int i=0;i<e[u].size();++i){
            int v=e[u][i].to;
            if (vis[v]) continue;
            p[v]=u;
            vis[v]=true;
            dep[v]=dep[u]+1;
            dis[v]=dis[u]+e[u][i].dis;
            que[++r]=v;
        }
    }
}
void getfa ()
{
    for (int j=0;(1<<j)<=n;++j){
        for (int i=1;i<=n;++i)
            fa[i][j]=-1;
    }
    for (int i=1;i<=n;++i){
        fa[i][0]=p[i];
    }
    for (int j=1;(1<<j)<=n;++j){
        for (int i=1;i<=n;++i)
            if (fa[i][j]!=-1)
            fa[i][j]=fa[fa[i][j-1]][j-1];
    }
}
int findlca (int x,int y)
{
    if (dep[x]<dep[y]) swap(x,y);
    while (dep[x]>dep[y]){
        int j=0;
        while (dep[fa[x][j]]>dep[y]) ++j;
        if (dep[fa[x][j]]==dep[y]){x=fa[x][j];break;}//这行很容易忘!!!!
        x=fa[x][j-1];
    }
    if (x==y) return y;
    while (x!=y){
        int j=0;
        while (fa[x][j]!=fa[y][j]&&fa[x][j]!=-1) ++j;
        if (j==0)
            break;
        x=fa[x][j-1];
        y=fa[y][j-1];
    }
    return fa[x][0];
}
int main()
{
    //freopen("de.txt","r",stdin);
    scanf("%d",&t);
    //printf("t=%d
",t);
    while (t--){
        init();
        scanf("%d",&n);
        scanf("%d",&q);
        //printf("n= %d
",n);
        for (int i=0;i<n-1;++i){
            int x,y,d;
            scanf("%d%d%d",&x,&y,&d);
            e[x].push_back(node(y,d));
            e[y].push_back(node(x,d));
        }
        bfs(1);
        getfa();
        for (int i=0;i<q;++i){
            int x,y;
            scanf("%d%d",&x,&y);
            //printf("%d %d
",x,y);
            int LCA=findlca(x,y);
            printf("%d
",dis[x]+dis[y]-2*dis[LCA]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/agenthtb/p/6659216.html