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;
}