#include using namespace std; #define INF 100000000 #define YJ 1145141919 #define INF_INT_MAX 2147483647 #define INF_LL 9223372036854775 #define INF_LL_MAX 9223372036854775807 #define EPS 1e-10 #define MOD 1000000007 #define MOD9 998244353 #define Pi acos(-1) #define LL long long #define ULL unsigned long long #define LD long double #define int long long using II = pair; int gcd(int a, int b) { return b != 0 ? gcd(b, a % b) : a; } int lcm(int a, int b) { return a * b / gcd(a, b); } int extgcd(int a, int b, int &x, int &y) { int g = a; x = 1; y = 0; if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x; return g; } #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define REP(i,n) FOR(i,0,n) #define ALL(a) begin((a)), end((a)) #define RALL(a) (a).rbegin(), (a).rend() #define PB push_back #define MP make_pair #define SZ(a) int((a).size()) #define MAX_V 100001 #define MAX_LOG_V 17 vector Edge[MAX_V]; //辺 vector Weight[MAX_V]; //parent[k][v]:ノードvにおける親を2^k回巡って //到達する頂点(根を通り過ぎる場合は-1) int parent[MAX_LOG_V][MAX_V]; //根からの深さ int depth[MAX_V]; //vに根とするものを指定すると //parentとdepthを計算してくれる関数 //dfs()で0を根とする木とみなす void dfs(int v = 0, int p = -1, int d = 0){ parent[0][v] = p; depth[v] = d; for(int i = 0; i < (int)Edge[v].size(); i++){ if(Edge[v][i] != p){ dfs(Edge[v][i], v, d+1); } } } //頂点数Vで初期化 void init(int V){ //0を根とする木を作成 dfs(); for(int k = 0; k+1 < MAX_LOG_V; k++){ for(int v = 0; v < V; v++){ if(parent[k][v] < 0) parent[k+1][v] = -1; else parent[k+1][v] = parent[k][parent[k][v]]; } } } //xとyのLCAを求める int lca(int x, int y){ //yの方が根から深くなるようにする if(depth[x] > depth[y]) swap(x,y); //yをxと同じ深さまで持ってくる for(int k = 0; k < MAX_LOG_V; k++){ if(((depth[y] - depth[x]) >> k) & 1){ y = parent[k][y]; } } //もし既に共通最近祖先にたどり着いたなら if(x == y) return x; //二分探索でLCAを求める for(int k = MAX_LOG_V - 1; k >= 0; k--){ if(parent[k][x] != parent[k][y]){ x = parent[k][x]; y = parent[k][y]; } } return parent[0][x]; } int N; void addEdge(int x, int y, int z) { Edge[x].push_back(y); Weight[x].push_back(z); } int sumW[MAX_V]; void calcSumW(int pos = 0, int pre = -1, int w = 0) { sumW[pos] = w; REP(n,Edge[pos].size()) { int next = Edge[pos][n]; int ww = Weight[pos][n]; if(next == pre) continue; calcSumW(next, pos, ww + w); } } signed main() { cin >> N; REP(n,N-1) { int x, y, z; cin >> x >> y >> z; addEdge(x,y,z); addEdge(y,x,z); } init(N); calcSumW(); int Q; cin >> Q; REP(q,Q) { int x[3]; cin >> x[0] >> x[1] >> x[2]; int ans = 0; REP(n,3) { int y = x[n], z = x[(n+1)%3]; int root = lca(y, z); ans += sumW[y] + sumW[z] - 2 * sumW[root]; } cout << ans/2 << endl; } return 0; }