How far away ?
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://acm.hdu.edu.cn/showproblem.php?pid=2586
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
HINT
题意
题解:
tarjan离线算法
代码:
# include<stdio.h> # include<string.h> # define N 40005 # define M 205 struct node{ int from,to,next,val; }edge[2*N]; struct node1{ int from,to,next,num; }edge1[2*M]; int tol,head[N],head1[N],tol1,father[N],dis[N],LCA[M],n,m; bool visit[N]; void add(int a,int b,int c) { edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];edge[tol].val=c;head[a]=tol++; } void add1(int a,int b,int c) { edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];edge1[tol1].num=c;head1[a]=tol1++; } int find(int x) { if(x!=father[x]) father[x]=find(father[x]); return father[x]; } void tarjan(int u) { int j,v; visit[u]=1; father[u]=u; ////////////////// for(j=head1[u];j!=-1;j=edge1[j].next) { v=edge1[j].to; if(visit[v]) LCA[edge1[j].num]=find(v); } ////////////////// for(j=head[u];j!=-1;j=edge[j].next) { v=edge[j].to; if(!visit[v]) { dis[v]=dis[u]+edge[j].val; tarjan(v); father[v]=u; } } } int main() { int i,ncase,a,b,c; scanf("%d",&ncase); while(ncase--) { scanf("%d%d",&n,&m); tol=0; memset(head,-1,sizeof(head)); for(i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } memset(visit,0,sizeof(visit)); tol1=0; memset(head1,-1,sizeof(head1)); for(i=1;i<=m;i++) { scanf("%d%d",&a,&b); add1(a,b,i); add1(b,a,i); } ///LCA是一种离线算法,所以刚开始需要把所有的询问都输入,然后用邻接表进行存储,i表示第i次询问 dis[1]=0; tarjan(1); for(i=0;i<tol1;i+=2) { a=edge1[i].from; b=edge1[i].to; c=edge1[i].num; printf("%d\n",dis[a]+dis[b]-2*dis[LCA[c]]); } } return 0; }