#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <sstream>
using namespace std;
#define Debug(x) (cerr << #x << " = " << (x) << endl)
#define Debug2(x, y) (cerr << #x << " = " << (x) << ", " << #y << " = " << (y) << endl)
typedef long long ll;
typedef pair<int,int> pii;
const int mod = 1e9;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int inf = 0x3f3f3f3f;
const int maxn = 50005;
vector<pii> g[maxn];
int root;
/********LCA***************/
//LCA(u,v) vs[id[u]<=i<=id[v]]中令depth[i]最小的i
int vs[maxn*2]; //DFS访问的顺序
int depth[maxn*2]; //节点的深度
int id[maxn]; //各个节点在vs中首次出现的下标
int dist[maxn];
void dfs(int u,int p,int d,int &k,int dd){
id[u] = k;
vs[k] = u;
dist[u] = dd;
depth[k++] = d;
for(int i=0;i<g[u].size();i++){
int v = g[u][i].first;
if(v == p)continue;
dfs(v,u,d+1,k,dd+g[u][i].second);
vs[k] = u;
depth[k++] = d;
}
}
/**************************/
/********RMQ***************/
int dp[20][maxn*2];
void rmq_init(int A[],int n){
for(int i=1;i<n;i++){
dp[0][i] = i;
//dp[0][i] = A[i];
}
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j+(1<<i)-1<n;j++){
if(A[dp[i-1][j]] < A[dp[i-1][j+(1<<(i-1))]]){
dp[i][j] = dp[i-1][j];
}
else {
dp[i][j] = dp[i-1][j+(1<<(i-1))];
}
// dp[i][j] = min(dp[i-1][j],dp[i-1][j+(1<<(i-1))]);
}
}
}
int query(int A[],int i,int j){
int k = log(j-i+1)/log(2);
if(A[dp[k][i]] < A[dp[k][j-(1<<k)+1]]) return dp[k][i];
else return dp[k][j-(1<<k)+1];
//return min(dp[k][i],dp[k][j-(1<<k)+1]);
}
/**************************/
//预处理
void init(int V){
int k = 0;
dfs(root,-1,0,k,0);
//预处理出RMQ (返回值不是最小值,而是最小值对应的下标)
rmq_init(depth,V*2);
}
int lca(int u,int v){
return vs[query(depth,min(id[u],id[v]),max(id[u],id[v]))];
}
/**************ZOJ3195******************/
int main(){
int n;
int cas = 1;
while(cin >> n){
if(cas != 1)printf("\n");
for(int i=0;i<n;i++){
g[i].clear();
}
for(int i=0;i<n-1;i++){
int u,v,l;
scanf("%d%d%d",&u,&v,&l);
g[u].push_back(pii(v,l));
g[v].push_back(pii(u,l));
}
root = 0;
init(n);
int Q;
cin >> Q;
while(Q --){
int a[3];
for(int i=0;i<3;i++){
scanf("%d",&a[i]);
}
int ans = 0;
for(int i=0;i<3;i++){
for(int j=i+1;j<3;j++){
int u = lca(a[i],a[j]);
ans += dist[a[i]]+dist[a[j]]-2*dist[lca(a[i],a[j])];
}
}
printf("%d\n",ans/2);
}
cas ++;
}
}
对于新搜索到的一个结点,首先创建由这个结点构成的集合,再对当前结点的每一个子树进行搜索,每搜索完一棵子树,则可确定子树内的LCA询问都已解决。其他的LCA询问的结果必然在这个子树之外,这时把子树所形成的集合与当前结点的集合合并,并将当前结点设为这个集合的祖先。之后继续搜索下一棵子树,直到当前结点的所有子树搜索完。这时把当前结点也设为已被检查过的,同时可以处理有关当前结点的LCA询问,如果有一个从当前结点到结点v的询问,且v已被检查过,则由于进行的是深度优先搜索,当前结点与v的最近公共祖先一定还没有被检查,而这个最近公共祖先的包涵v的子树一定已经搜索过了,那么这个最近公共祖先一定是v所在集合的祖先。(dongxicheng.org/structure/lca-rmq/)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <sstream>
using namespace std;
#define Debug(x) (cerr << #x << " = " << (x) << endl)
#define Debug2(x, y) (cerr << #x << " = " << (x) << ", " << #y << " = " << (y) << endl)
typedef long long ll;
typedef pair<int,int> pii;
const int mod = 1e9;
ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int inf = 0x3f3f3f3f;
const int maxn = 50005;
/*********Disjoint Set********/
int fa[maxn];
//void init(){
// memset(fa,-1,sizeof(fa));
//}
int find(int x){
if(fa[x] == x)return x;
return fa[x] = find(fa[x]);
}
void Unon(int x,int y){
int fx = find(x);
int fy = find(y);
if(fx != fy){
fa[fx] = fy;
}
}
/*****************************/
vector<pii> g[maxn];
int root;
int dist[maxn];
/**********LCA(Tarjan)********/
bool vis[maxn];
vector<pii> qr[maxn];
const int maxq = 70005;
int ans[maxq*3];
void Tarjan(int u,int pre){
fa[u] = u;
for(int i=0;i<g[u].size();i++){
int v = g[u][i].first;
int d = g[u][i].second;
if(v == pre)continue;
dist[v] = dist[u] + d;
Tarjan(v,u);
Unon(u,v);
fa[find(u)] = fa[u] = u;
}
vis[u] = true;
for(int i=0;i<qr[u].size();i++){
int v = qr[u][i].first;
int s = qr[u][i].second;
if(vis[v] == true){
ans[s] = dist[u]+dist[v]-2*dist[fa[find(v)]];
}
}
}
int QQ[70005][3];
/**************ZOJ3195******************/
int main(){
int n;
int cas = 1;
while(cin >> n){
if(cas != 1)printf("\n");
for(int i=0;i<n;i++){
g[i].clear();
qr[i].clear();
}
for(int i=0;i<n-1;i++){
int u,v,l;
scanf("%d%d%d",&u,&v,&l);
g[u].push_back(pii(v,l));
g[v].push_back(pii(u,l));
}
//init(n);
int Q;
cin >> Q;
for(int q=0;q<Q;q++){
for(int i=0;i<3;i++){
scanf("%d",&QQ[q][i]);
}
int cnt = 0;
for(int i=0;i<3;i++){
for(int j=i+1;j<3;j++){
int u = QQ[q][i];
int v = QQ[q][j];
qr[u].push_back(pii(v,q*3+(cnt)));
qr[v].push_back(pii(u,q*3+(cnt)));
cnt ++;
}
}
}
memset(vis,false,sizeof(vis));
root = 0;
dist[root] = 0;
Tarjan(root,-1);
for(int i=0;i<Q;i++){
int res = 0;
for(int j=0;j<3;j++){
res += ans[i*3+j];
}
res /= 2;
printf("%d\n",res);
}
cas ++;
}
}