题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586
(包括2016级新生)除了校赛,还有什么途径可以申请加入ACM校队? |
How far away ?Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10769 Accepted Submission(s): 3928
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
Sample Output
|
注意题目有误,题目说每个测试样例后面要输出空行,但是样例并没有输出。所以不用空行
用l[i]表示i到根节点的距离。那么要求a和b点的距离就是l[a]+l[b]-2*[lca[a,b]] 我用的在线算法
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 40010
int dp[2*N][20];
int head[N],p[N];
int dep[2*N],f[2*N];
int flag[N],cnt;
int l[N];
struct Edge
{
int to,next;
int len;
} edge[2*N];
void init(int n)
{
cnt=0;
for(int i=0; i<=n; i++)
{
head[i]=-1;
flag[i]=0;
}
memset(l,0,sizeof(l));
}
void addedge(int s,int e,int len)
{
edge[cnt].to=e;
edge[cnt].next=head[s];
edge[cnt].len=len;
head[s]=cnt++;
}
void dfs(int u,int d)
{
f[cnt]=u;
dep[cnt]=d;
p[u]=cnt++;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].to;
l[v]=l[u]+edge[i].len;
dfs(v,d+1);
f[cnt]=u;
dep[cnt++]=d;
}
}
void makermq()
{
for(int i=0; i<cnt; i++)
dp[i][0]=i;
for(int j=1; (1<<j)<=cnt; j++)
{
for(int i=0; i+(1<<j)-1<cnt; i++)
{
if(dep[dp[i][j-1]]<dep[dp[i+(1<<(j-1))][j-1]])
dp[i][j]=dp[i][j-1];
else
dp[i][j]=dp[i+(1<<(j-1))][j-1];
}
}
}
int finds(int s,int e)
{
if(s>e)
{
int t=s;
s=e;
e=t;
}
int k=(int)(log(e-s+1.0)/log(2.0));
if(dep[dp[s][k]]<dep[dp[e-(1<<k)+1][k]])
return dp[s][k];
return dp[e-(1<<k)+1][k];
}
void LCA(int root,int n,int m)
{
cnt=0;
dfs(root,0);
makermq();
int s,e;
while(m--)
{
scanf("%d %d",&s,&e);
int t=f[finds(p[s],p[e])];
printf("%d\n",l[s]+l[e]-2*l[t]);
}
}
int main()
{
int T,n,m,len;
int s,e,root;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
init(n);
for(int i=1; i<n; i++)
{
scanf("%d %d %d",&s,&e,&len);
addedge(s,e,len);
flag[e]=1;
}
for(int i=1; i<=n; i++)
if(!flag[i])
{
root=i;
break;
}
LCA(root,n,m);
}
return 0;
}