How far away ?
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 21250 Accepted Submission(s): 8368
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
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
题目大意:给一个有权树,有Q次询问,求任意两点的距离。
题目分析:在树中有一个性质:任意两点的距离 ANS = dist[ u ] + dist[ v ] - dist[ lca(u,v) ],其中dist[ I ]是根到 I 的 距离 ,由于需要多次询问,所以使用Tarjan离线求LCA比较快
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<queue>
5 #include<vector>
6 using namespace std;
7 const int maxn=40005;
8 struct edge{
9 int to;
10 int len;
11 };
12 vector<struct edge>G[maxn];
13 vector<int>qury[maxn];
14 vector<int>num[maxn];
15 int dis[maxn],vis[maxn],ans[maxn],fa[maxn];
16 void init()
17 {
18 memset(dis,0,sizeof(dis));
19 memset(vis,0,sizeof(vis));
20 for(int i = 0 ; i < 40005 ; i++)
21 {
22 G[i].clear();
23 qury[i].clear();
24 num[i].clear();
25 fa[i]=i;
26 }
27 }
28 int find(int x)
29 {
30 int xx=x;
31 while(fa[x]!=x)
32 {
33 x=fa[x];
34 }
35 while(fa[xx]!=x)
36 {
37 int t=fa[xx];
38 fa[xx]=x;
39 xx=t;
40 }
41 return x;
42 }
43 void Union(int x,int y)
44 {
45 int xx=find(x);
46 int yy=find(y);
47 if(xx!=yy);
48 fa[yy]=xx;//在完成子节点的Tarjan遍历之后,把子节点纳入父节点名下
49 }
50 void Tarjan(int u,int ll)
51 {
52 vis[u]=1;
53 dis[u]=ll;
54 for(int i = 0 ; i< G[u].size() ;i++)
55 {
56 struct edge wqw=G[u][i];
57 if(vis[wqw.to])continue;
58 Tarjan(wqw.to,wqw.len+ll);
59 Union(u,wqw.to);
60 }
61 for(int i = 0 ; i < qury[u].size() ; i++)
62 {
63 if(vis[qury[u][i]])
64 {
65 ans[num[u][i]]=dis[u]+dis[qury[u][i]]-2*dis[find(qury[u][i])];
66 }
67 }
68 }
69 int main()
70 {
71 int t;
72 scanf("%d",&t);
73 while(t--)
74 {
75 init();
76 int n,m;
77 scanf("%d%d",&n,&m);
78 for(int i = 1 ; i < n ; i++)
79 {
80 int a,b,c;
81 scanf("%d%d%d",&a,&b,&c);
82 G[a].push_back((struct edge){b,c});
83 G[b].push_back((struct edge){a,c});
84 }
85 for(int i = 0 ; i < m ; i++)
86 {
87 int a,b;
88 scanf("%d%d",&a,&b);
89 qury[a].push_back(b);
90 qury[b].push_back(a);
91 num[a].push_back(i);
92 num[b].push_back(i);
93 }
94 Tarjan(1,0);
95 for(int i = 0 ; i < m ; i++)
96 {
97 printf("%d
",ans[i]);
98 }
99 }
100 return 0;
101 }