import java.util.*;
class Solution {
static final int MOD = 1_000_000_007;
static final int LOG = 17;
List<Integer>[] graph;
int[][] up;
int[] depth;
public int[] assignEdgeWeights(int[][] edges, int[][] queries) {
int n = edges.length + 1;
graph = new ArrayList[n + 1];
for (int i = 1; i <= n; i++) {
graph[i] = new ArrayList<>();
}
for (int[] e : edges) {
graph[e[0]].add(e[1]);
graph[e[1]].add(e[0]);
}
up = new int[n + 1][LOG + 1];
depth = new int[n + 1];
dfs(1, 0);
for (int j = 1; j <= LOG; j++) {
for (int i = 1; i <= n; i++) {
up[i][j] = up[up[i][j - 1]][j - 1];
}
}
int maxDepth = n;
long[] pow2 = new long[maxDepth + 1];
pow2[0] = 1;
for (int i = 1; i <= maxDepth; i++) {
pow2[i] = (pow2[i - 1] * 2) % MOD;
}
int[] ans = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int u = queries[i][0];
int v = queries[i][1];
int lca = getLCA(u, v);
int len = depth[u] + depth[v] - 2 * depth[lca];
if (len == 0) {
ans[i] = 0;
} else {
ans[i] = (int) pow2[len - 1];
}
}
return ans;
}
private void dfs(int node, int parent) {
up[node][0] = parent;
for (int nxt : graph[node]) {
if (nxt == parent) continue;
depth[nxt] = depth[node] + 1;
dfs(nxt, node);
}
}
private int getLCA(int u, int v) {
if (depth[u] < depth[v]) {
int temp = u;
u = v;
v = temp;
}
int diff = depth[u] - depth[v];
for (int j = LOG; j >= 0; j--) {
if (((diff >> j) & 1) == 1) {
u = up[u][j];
}
}
if (u == v) return u;
for (int j = LOG; j >= 0; j--) {
if (up[u][j] != up[v][j]) {
u = up[u][j];
v = up[v][j];
}
}
return up[u][0];
}
}
TIME COMPLEXITY
SPACE COMPLEXITY