/*
Problem: Finding best charging station location in a tree
You have a tree with n nodes (cities) rooted at node 1.
Each edge has a weight (distance).
For each query, you're given:
- u, v: two cities that need to receive deliveries
- c: total fuel capacity
You need to choose a starting city 's' where:
- Cars go from s down to u (delivery 1)
- Cars go from s down to v (delivery 2)
- Cars go from s up to root (return to headquarters)
- Total distance traveled <= c (fuel capacity)
Goal: Among all valid starting cities, maximize the fuel used.
If no valid starting city exists, output 0.
==================================================================================
HOW WE SOLVE THIS:
==================================================================================
OBSERVATION 1: Where can we start from?
The starting city 's' must be able to reach both u and v by going downwards.
This means s must be an ANCESTOR of both u and v.
In other words, s must be somewhere on the path from root to both u and v.
The deepest common ancestor of u and v is their LCA (Lowest Common Ancestor).
So s can be any node from root to LCA(u,v).
OBSERVATION 2: How do we calculate distances?
Let dist[x] = distance from root to node x (sum of edge weights on path)
For any ancestor s of both u and v:
- Distance from s to u = dist[u] - dist[s] (going down)
- Distance from s to v = dist[v] - dist[s] (going down)
- Distance from s to root = dist[s] (going up)
Total fuel used = (dist[u] - dist[s]) + (dist[v] - dist[s]) + dist[s]
= dist[u] + dist[v] - dist[s]
OBSERVATION 3: What's the constraint?
We need: dist[u] + dist[v] - dist[s] <= c
Rearranging: dist[s] >= dist[u] + dist[v] - c
Let's call (dist[u] + dist[v] - c) the "minimum_distance"
We need: dist[s] >= minimum_distance
OBSERVATION 4: How do we maximize fuel used?
Fuel used = dist[u] + dist[v] - dist[s]
Since dist[u] and dist[v] are fixed, to maximize this we need to MINIMIZE dist[s].
So we want the SMALLEST dist[s] that still satisfies dist[s] >= minimum_distance.
STRATEGY:
1. Find LCA of u and v (call it L)
2. Calculate minimum_distance = dist[u] + dist[v] - c
3. If minimum_distance > dist[L], no valid s exists → output 0
4. Otherwise, find the highest ancestor of L with dist >= minimum_distance
5. This gives us the s with smallest valid dist[s], maximizing fuel used
IMPLEMENTATION DETAILS:
- Use binary lifting to quickly find LCA
- Use binary lifting to jump to the right ancestor
- Precompute distances from root using DFS
- Use __int128 to avoid overflow when adding large distances
Example:
Tree: 1 (root)
/ \
2 3
/
4
dist[1]=0, dist[2]=5, dist[3]=8, dist[4]=12
Query: u=4, v=3, c=20
- LCA(4,3) = 1
- minimum_distance = 12 + 8 - 20 = 0
- Find highest ancestor of 1 with dist >= 0 → that's 1 itself
- Answer = 12 + 8 - 0 = 20 ✓
Time complexity: O(n log n) preprocessing + O(log n) per query
Space complexity: O(n log n) for binary lifting table
==================================================================================
*/
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int num_cities, num_queries;
cin >> num_cities >> num_queries;
// Build the tree as an adjacency list
// graph[city] = list of {neighbor, edge_weight}
vector<vector<pair<int, long long>>> graph(num_cities + 1);
for(int i = 0; i < num_cities - 1; i++){
int city_a, city_b;
long long road_length;
cin >> city_a >> city_b >> road_length;
graph[city_a].push_back({city_b, road_length});
graph[city_b].push_back({city_a, road_length});
}
// Prepare for binary lifting (jumping up the tree quickly)
// We need log2(n) levels of jumps
int max_jumps = 1;
while((1 << max_jumps) <= num_cities) {
max_jumps++;
}
// ancestor[jump_size][city] = where you end up if you jump 2^jump_size steps up from city
vector<vector<int>> ancestor(max_jumps, vector<int>(num_cities + 1, 0));
// Basic info about each city
vector<int> level(num_cities + 1, 0); // how deep in the tree (root is 0)
vector<long long> distance_from_root(num_cities + 1, 0); // total distance from root
// Build the tree structure using DFS from root (city 1)
vector<int> parent_of(num_cities + 1, 0);
vector<int> dfs_stack;
dfs_stack.reserve(num_cities);
dfs_stack.push_back(1);
parent_of[1] = 0; // root has no parent
level[1] = 0;
distance_from_root[1] = 0;
while(!dfs_stack.empty()){
int city = dfs_stack.back();
dfs_stack.pop_back();
// Set up first level of binary lifting (jump 1 step = go to parent)
ancestor[0][city] = parent_of[city];
// Visit all neighbors
for(auto [neighbor, road_length] : graph[city]){
// Don't go back to parent
if(neighbor == parent_of[city]) continue;
parent_of[neighbor] = city;
level[neighbor] = level[city] + 1;
distance_from_root[neighbor] = distance_from_root[city] + road_length;
dfs_stack.push_back(neighbor);
}
}
// Build the rest of the binary lifting table
// Jump 2^j steps = jump 2^(j-1) steps twice
for(int jump_size = 1; jump_size < max_jumps; jump_size++){
for(int city = 1; city <= num_cities; city++){
int halfway = ancestor[jump_size - 1][city];
if(halfway != 0) {
ancestor[jump_size][city] = ancestor[jump_size - 1][halfway];
} else {
ancestor[jump_size][city] = 0;
}
}
}
// Function: find the lowest common ancestor of two cities
auto find_lca = [&](int city_a, int city_b) {
// Make sure city_a is deeper (or same depth)
if(level[city_a] < level[city_b]) {
swap(city_a, city_b);
}
// Bring city_a up to the same level as city_b
int level_difference = level[city_a] - level[city_b];
for(int jump = 0; jump < max_jumps; jump++){
if(level_difference & (1 << jump)) {
city_a = ancestor[jump][city_a];
}
}
// If they're the same now, we found the LCA
if(city_a == city_b) return city_a;
// Otherwise, jump both up until their parents are the same
for(int jump = max_jumps - 1; jump >= 0; jump--){
if(ancestor[jump][city_a] != ancestor[jump][city_b]){
city_a = ancestor[jump][city_a];
city_b = ancestor[jump][city_b];
}
}
// Now their parent is the LCA
return ancestor[0][city_a];
};
// Function: find the highest ancestor with distance >= threshold
// (closest to root while still satisfying the constraint)
auto find_highest_valid_ancestor = [&](int city, __int128 min_distance) {
int current = city;
// Try jumping up as far as possible while staying valid
for(int jump = max_jumps - 1; jump >= 0; jump--){
int parent = ancestor[jump][current];
// Can we jump this far and still be valid?
if(parent != 0 && (__int128)distance_from_root[parent] >= min_distance) {
current = parent;
}
}
return current;
};
// Process each query
while(num_queries--){
int delivery_1, delivery_2;
long long fuel_capacity;
cin >> delivery_1 >> delivery_2 >> fuel_capacity;
// Find the deepest possible starting point (LCA)
int lowest_common = find_lca(delivery_1, delivery_2);
// Calculate the minimum distance our starting point must have from root
// Use __int128 to prevent overflow when adding large distances
__int128 sum_distances = (__int128)distance_from_root[delivery_1] +
(__int128)distance_from_root[delivery_2];
__int128 min_distance = sum_distances - (__int128)fuel_capacity;
// If even the deepest valid point (LCA) doesn't have enough distance, no solution
if(min_distance > (__int128)distance_from_root[lowest_common]){
cout << 0 << "\n";
continue;
}
// If we can start from root itself, do that (uses most fuel)
if(min_distance <= 0){
// Check if total distance fits in capacity
if(sum_distances <= (__int128)fuel_capacity) {
// Safe to convert back to long long since it fits in capacity
cout << (long long)sum_distances << "\n";
} else {
cout << 0 << "\n";
}
continue;
}
// Find the best starting city (highest ancestor with valid distance)
int start_city = find_highest_valid_ancestor(lowest_common, min_distance);
// Calculate how much fuel we'd use
// Use __int128 to prevent overflow
__int128 fuel_used = sum_distances - (__int128)distance_from_root[start_city];
// Make sure we don't exceed capacity (should always be true, but be safe)
if(fuel_used <= (__int128)fuel_capacity) {
cout << (long long)fuel_used << "\n";
} else {
cout << 0 << "\n";
}
}
return 0;
}