hdu 2586 How far away? 【LCA】 解题报告

来源:互联网 发布:德国 帅哥 推倒 知乎 编辑:程序博客网 时间:2024/06/16 15:35

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

Output

For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.

思路

LCA

题目大意:一个村子里有n个房子,这n个房子用n-1条路连接起来,接下了有m次询问,每次询问两个房子a,b之间的距离是多少。

很明显的最近公共祖先问题,先建一棵树,然后求出每一点i到树根的距离dis[i],然后每次询问a,b之间的距离=dis[a]+dis[b]-2*dis[LCA(a,b)];

LCA(a,b)即是a,b的最近公共祖先。。

代码

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>#include<vector>using namespace std;const int N=40000+5;const int M=200+5;struct node{    int u,v,next,w;}edge[2*N];struct node1{    int u,v,next,num;}edge1[2*M];int T,num,num1,n,m;int head[N],head1[N],father[N],dis[N],LCA[M],visit[N];void build(int u,int v,int w){    edge[num].u=u;    edge[num].v=v;    edge[num].w=w;    edge[num].next=head[u];    head[u]=num++;}void build1(int u,int v,int w){    edge1[num1].u=u;    edge1[num1].v=v;    edge1[num1].num=w;    edge1[num1].next=head1[u];    head1[u]=num1++;}int getfather(int x){    if (x!=father[x]) father[x]=getfather(father[x]);    return father[x];}void tarjan(int u){    int v;    visit[u]=1;    father[u]=u;    for (int j=head1[u];j!=-1;j=edge1[j].next)    {        v=edge1[j].v;        if (visit[v]) LCA[edge1[j].num]=getfather(v);    }    for (int j=head[u];j!=-1;j=edge[j].next)    {        v=edge[j].v;        if (!visit[v])         {            dis[v]=dis[u]+edge[j].w;            tarjan(v);            father[v]=u;        }    }}int main(){    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        num=0,num1=0;        memset(head,-1,sizeof(head));        for (int i=1;i<n;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            build(a,b,c);            build(b,a,c);        }        memset(visit,0,sizeof(visit));        memset(head1,-1,sizeof(head1));        for (int i=1;i<=m;i++)        {            int a,b;            scanf("%d%d",&a,&b);            build1(a,b,i);            build1(b,a,i);        }        dis[1]=0;        tarjan(1);        for (int i=0;i<num1;i+=2)        {            int a,b,c;            a=edge1[i].u;            b=edge1[i].v;            c=edge1[i].num;            printf("%d\n",dis[a]+dis[b]-2*dis[LCA[c]]);        }    }    return 0;}
原创粉丝点击