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.
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
解题思路:Tarjan算法求树上任意两点的最短路。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn=40005; 5 const int maxv=205; 6 int T,n,m,x,y,z,fa[maxn],dist[maxn],ans[maxv];bool vis[maxn]; 7 vector<pair<int,int> > tree[maxn],query[maxn]; 8 void init(){ 9 for(int i=1;i<=n;++i)fa[i]=i,tree[i].clear(),query[i].clear(); 10 memset(vis,false,sizeof(vis)); 11 memset(dist,0,sizeof(dist)); 12 memset(ans,0,sizeof(ans)); 13 } 14 int query_father(int x){ 15 int per=x,tmp; 16 while(fa[per]!=per)per=fa[per]; 17 while(x!=per){tmp=fa[x];fa[x]=per;x=tmp;}//路径压缩 18 return x; 19 } 20 void unite(int x,int y){ 21 x=query_father(x),y=query_father(y); 22 if(x!=y)fa[y]=x; 23 } 24 void Tarjan_LCA(int cur,int val){ 25 vis[cur]=true;///先标记为true,这样如果同一支树上前面的祖先节点已访问,但是还没有归并到集合中去相当于为其本身,所以对下面计算两个节点的最近距离是没有影响的 26 dist[cur]=val; 27 for(size_t i=0;i<tree[cur].size();++i){ 28 int v=tree[cur][i].first; 29 int w=tree[cur][i].second; 30 if(!vis[v]){ 31 Tarjan_LCA(v,val+w);///先序遍历 32 unite(cur,v);///回退后续遍历归并集合 33 } 34 } 35 for(size_t i=0;i<query[cur].size();++i){///同时扫描与cur有关的点对查询 36 int to=query[cur][i].first; 37 int id=query[cur][i].second; 38 if(vis[to])ans[id]=dist[cur]+dist[to]-2*dist[query_father(to)]; 39 } 40 } 41 int main(){ 42 while(~scanf("%d",&T)){ 43 while(T--){ 44 scanf("%d%d",&n,&m); 45 init(); 46 for(int i=1;i<n;++i){ 47 scanf("%d%d%d",&x,&y,&z); 48 tree[x].push_back(make_pair(y,z)); 49 tree[y].push_back(make_pair(x,z)); 50 } 51 for(int i=1;i<=m;++i){ 52 scanf("%d%d",&x,&y); 53 query[x].push_back(make_pair(y,i)); 54 query[y].push_back(make_pair(x,i)); 55 } 56 Tarjan_LCA(1,0); 57 for(int i=1;i<=m;++i)printf("%d ",ans[i]); 58 } 59 } 60 return 0; 61 }