hdu 2586 How far away

How far away ?

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 11699    Accepted Submission(s): 4300

Problem Description
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.
 
Input
First 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.
 
Output
For 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
 
Source
ECJTU 2009 Spring Contest
一道lca入门题,题目大意是给定n户房屋,n-1条道路,询问两两房屋间的距离。我的思路是,由于是无向图,所以无固定树根,任意选节点都可。所以,先选定点1作为根,进行bfs和树上倍增。最终用距离公式dis[x]+dis[y]-2*dis[lca(x,y)]求出两房屋间的距离,其实这个公式还是蛮易懂的。不过在next这个数组名上栽了,CE滚粗。只好忍痛将next改为mnext,降低可读性。。。
17486822    2016-07-10 21:36:39    Accepted    2586    31MS    10308K    2038B    G++    ksq2013
hdu上测的,不知道为什么用宽搜比我的同学慢了两倍,是因为数组开太大吗???真心无语。。。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
bool vis[80100];
int n,bin[20],q[50100],dis[80100],deep[80100],fa[80100][20];
int u[80100],v[80100],w[80100],first[80100],mnext[80100];
void make_bin()
{
    bin[0]=1;
    for(int i=1;i<=16;i++)
        bin[i]=bin[i-1]<<1;
}
void Init()
{
    memset(vis,false,sizeof(vis));
    memset(fa,0,sizeof(fa));
    memset(mnext,0,sizeof(mnext));
    memset(first,0,sizeof(first));
    memset(q,0,sizeof(q));
    memset(dis,0,sizeof(dis));
    memset(deep,0,sizeof(deep));
}
void Link()
{
    for(int i=1;i<=n-1;i++){
        scanf("%d%d%d",&u[i],&v[i],&w[i]);
        u[i+n-1]=v[i];v[i+n-1]=u[i];w[i+n-1]=w[i];
        mnext[i]=first[u[i]];
        mnext[i+n-1]=first[v[i]];
        first[i]=i;
        first[v[i]]=i+n-1;
    }
}
void bfs()
{
    int head=0,tail=1;
    q[0]=1;vis[1]=true;
    while(head^tail){
        int now=q[head];head++;
        for(int i=1;i<=16;i++)
            if(bin[i]<=deep[now])
                fa[now][i]=fa[fa[now][i-1]][i-1];
            else break;
        for(int i=first[now];i&&v[i]^now;i=mnext[i])
            if(!vis[v[i]]){
                vis[v[i]]=true;
                fa[v[i]][0]=now;
                deep[v[i]]=deep[now]+1;
                dis[v[i]]=dis[now]+w[i];
                q[tail++]=v[i];
            }
    }
}
int lca(int x,int y)
{
    int t=deep[x]-deep[y];
    for(int i=0;i<=16;i++)
        if(t&bin[i])
            x=fa[x][i];
    for(int i=16;i>=0;i--)
        if(fa[x][i]^fa[y][i])
            x=fa[x][i],y=fa[y][i];
    if(!(x^y))return y;
    return fa[x][0];
}
int main()
{
    make_bin();
    int T;
    scanf("%d",&T);
    for(;T;T--){
        Init();
        int m;
        scanf("%d%d",&n,&m);
        Link();
        bfs();
        for(int x,y;m;m--){
            scanf("%d%d",&x,&y);
            if(deep[x]<deep[y])swap(x,y);
            printf("%d
",dis[x]+dis[y]-2*dis[lca(x,y)]);
        }
    }
    return 0;
}



原文地址:https://www.cnblogs.com/keshuqi/p/5957767.html