Obviously, it's kind of LCA problem.
I assume that you guys have already learned about LCA stuff :).
So I just talk about the main idea of my method.
Our goal is to connect three specific node by using shortest path.
So we choose a node as root (ie. 0), transform the tree to an array (LCA->RMQ), calculate the depth of each node and get the distance between root and all nodes.
define:
ta: tree array
dep[i]: depth of node i
dis[i]: the distance between root and node i
Then, for each query, we calculate the LCA to each pair of nodes.
Sort all the nodes(include that three nodes and their LCA) in ascending order according to their depth.
Delete all duplicate elements in the array(use unique function)
Then scan the array sequentially.
For each element a[i] we scan the array again but in reverse direction until we find an ta[j] (j < i) that LCA(ta[i], ta[j]) = ta[j], then calculate the distance dis[ta[i]] - dis[ta[j]] and add it to the result, break sub-scan.
why? because we sort them in ascending order, the most lowest ancient of a[i] must be the righest ta[j] (LCA(ta[i], ta[j]) = ta[j]).
Besides, it's a tree which mean that there only exists one path between any two node, we can add dis[ta[i]] - dis[ta[j]] to the result without any duplicates.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cctype>
#include <queue>
#include <stack>
using namespace std;
#define MS(c, a) memset(c, a, sizeof c)
#define Rep(c, a, b) for (int c = (a); c < (b); c++)
#define Nre(c, a, b) for (int c = (a); c > (b); c--)
#define MAXN (50050 << 1)
struct Edge
{
int v, w, next;
};
vector<Edge> E;
int L[MAXN];
void G_ini() //Graph initialize
{
E.clear();
MS(L, -1);
}
void AE(int u, int v, int w) //Add Edge
{
Edge te = {v, w, L[u]};
L[u] = E.size();
E.push_back(te);
}
int n, q, dep[MAXN], ind, ta[MAXN], id[MAXN], dis[MAXN];
void TTI(int u, int fa) //Tree to Interval
{
if (fa != -1) dep[u] = dep[fa] + 1;
id[u] = ind;
ta[ind++] = u;
for (int i = L[u]; i != -1; i = E[i].next)
if (E[i].v != fa)
{
dis[E[i].v] = dis[u] + E[i].w;
TTI(E[i].v, u);
ta[ind++] = u;
}
}
int st[20][MAXN];
int low(int x) //lowest power
{
int o = 0;
while ((1 << o) <= x) o++;
return o;
}
void st_ini() //sparse table initialize
{
Rep(i, 0, ind) st[0][i] = ta[i];
int l = low(ind);
Rep(i, 1, l) Rep(j, 0, ind)
if (j + (1 << i) < ind)
{
int x = st[i - 1][j],
y = st[i - 1][j + (1 << (i - 1))];
st[i][j] = (dep[x] < dep[y])? x: y;
}
}
int rmq(int x, int y) //Range minimum query
{
x = id[x];
y = id[y];
if (x > y) swap(x, y);
int l = low(y - x + 1) - 1;
x = st[l][x];
y = st[l][y - (1 << l) + 1];
return (dep[x] < dep[y])? x: y;
}
bool cmp(int p, int q)
{
if (dep[p] != dep[q]) return dep[p] < dep[q];
return p < q;
}
int main()
{
bool spa = 0;
while (~scanf("%d", &n))
{
if (spa) puts("");
spa = 1;
G_ini();
Rep(i, 0, n - 1)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
AE(u, v, w);
AE(v, u, w);
}
MS(dep, 0);
MS(dis, 0);
TTI(ind = 0, -1); //LCA->RMQ
st_ini();
scanf("%d", &q);
vector<int> x;
while (q--)
{
int tx;
x.clear();
Rep(i, 0, 3)
{
scanf("%d", &tx);
x.push_back(tx);
}
tx = x.size();
Rep(i, 0, tx) Rep(j, 0, tx) //Calculate LCA of all pair of nodes and add it to the candidate array
x.push_back(rmq(x[i], x[j]));
sort(x.begin(), x.end(), cmp); //Sort them in ascending order according to their depth
x.erase(unique(x.begin(), x.end()), x.end()); //Delete duplicate element
int res = 0; //Result
Rep(i, 1, x.size())
Nre(j, i - 1, -1)
{
if (rmq(x[i], x[j]) == x[j]) //find the lowest ancient, add the distance to result and break
{
res += dis[x[i]] - dis[x[j]];
break;
}
}
printf("%d\n", res);
}
}
return 0;
}