From 3ebd3f4362f9fc68cd3cfcafe770e90bc16384d8 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 5 Sep 2023 20:13:16 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.2846 No.2846.Minimum Edge Weight Equilibrium Queries in a Tree --- .../README.md | 274 +++++++++++++++++- .../README_EN.md | 252 +++++++++++++++- .../Solution.cpp | 67 +++++ .../Solution.go | 73 +++++ .../Solution.java | 67 +++++ .../Solution.py | 43 +++ 6 files changed, 769 insertions(+), 7 deletions(-) create mode 100644 solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.cpp create mode 100644 solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.go create mode 100644 solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.java create mode 100644 solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.py diff --git a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README.md b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README.md index 3f3dbb20e771a..16e2322cdd89c 100644 --- a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README.md +++ b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README.md @@ -65,6 +65,26 @@ +**方法一:倍增法求 LCA** + +题目求的是任意两点的路径上,将其所有边的权重变成相同值的最小操作次数。实际上就是求这两点之间的路径长度,减去路径上出现次数最多的边的次数。 + +而求两点间的路径长度,可以通过倍增法求 LCA 来实现。我们记两点分别为 $u$ 和 $v$,最近公共祖先为 $x$,那么 $u$ 到 $v$ 的路径长度就是 $depth(u) + depth(v) - 2 \times depth(x)$。 + +另外,我们可以用一个数组 $cnt[n][26]$ 记录根节点到每个节点上,每个边权重出现的次数。那么 $u$ 到 $v$ 的路径上,出现次数最多的边的次数就是 $\max_{0 \leq j < 26} cnt[u][j] + cnt[v][j] - 2 \times cnt[x][j]$。其中 $x$ 为 $u$ 和 $v$ 的最近公共祖先。 + +倍增法求 LCA 的过程如下: + +我们记每个节点的深度为 $depth$,父节点为 $p$,而 $f[i][j]$ 表示节点 $i$ 的第 $2^j$ 个祖先。那么,对于任意两点 $x$ 和 $y$,我们可以通过以下方式求出它们的最近公共祖先: + +1. 如果 $depth(x) < depth(y)$,那么交换 $x$ 和 $y$,即保证 $x$ 的深度不小于 $y$ 的深度; +2. 接下来,我们将 $x$ 的深度不断向上提升,直到 $x$ 和 $y$ 的深度相同,此时 $x$ 和 $y$ 的深度都为 $depth(x)$; +3. 然后,我们将 $x$ 和 $y$ 的深度同时向上提升,直到 $x$ 和 $y$ 的父节点相同,此时 $x$ 和 $y$ 的父节点都为 $f[x][0]$,即为 $x$ 和 $y$ 的最近公共祖先。 + +最后,节点 $u$ 到节点 $v$ 的最小操作次数就是 $depth(u) + depth(v) - 2 \times depth(x) - \max_{0 \leq j < 26} cnt[u][j] + cnt[v][j] - 2 \times cnt[x][j]$。 + +时间复杂度 $O((n + q) \times C \times \log n)$,空间复杂度 $O(n \times C \times \log n)$,其中 $C$ 为边权重的最大值。 + ### **Python3** @@ -72,7 +92,49 @@ ```python - +class Solution: + def minOperationsQueries( + self, n: int, edges: List[List[int]], queries: List[List[int]] + ) -> List[int]: + m = n.bit_length() + g = [[] for _ in range(n)] + f = [[0] * m for _ in range(n)] + p = [0] * n + cnt = [None] * n + depth = [0] * n + for u, v, w in edges: + g[u].append((v, w - 1)) + g[v].append((u, w - 1)) + cnt[0] = [0] * 26 + q = deque([0]) + while q: + i = q.popleft() + f[i][0] = p[i] + for j in range(1, m): + f[i][j] = f[f[i][j - 1]][j - 1] + for j, w in g[i]: + if j != p[i]: + p[j] = i + cnt[j] = cnt[i][:] + cnt[j][w] += 1 + depth[j] = depth[i] + 1 + q.append(j) + ans = [] + for u, v in queries: + x, y = u, v + if depth[x] < depth[y]: + x, y = y, x + for j in reversed(range(m)): + if depth[x] - depth[y] >= (1 << j): + x = f[x][j] + for j in reversed(range(m)): + if f[x][j] != f[y][j]: + x, y = f[x][j], f[y][j] + if x != y: + x = p[x] + mx = max(cnt[u][j] + cnt[v][j] - 2 * cnt[x][j] for j in range(26)) + ans.append(depth[u] + depth[v] - 2 * depth[x] - mx) + return ans ``` ### **Java** @@ -80,19 +142,223 @@ ```java - +class Solution { + public int[] minOperationsQueries(int n, int[][] edges, int[][] queries) { + int m = 32 - Integer.numberOfLeadingZeros(n); + List[] g = new List[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + int[][] f = new int[n][m]; + int[] p = new int[n]; + int[][] cnt = new int[n][0]; + int[] depth = new int[n]; + for (var e : edges) { + int u = e[0], v = e[1], w = e[2] - 1; + g[u].add(new int[] {v, w}); + g[v].add(new int[] {u, w}); + } + cnt[0] = new int[26]; + Deque q = new ArrayDeque<>(); + q.offer(0); + while (!q.isEmpty()) { + int i = q.poll(); + f[i][0] = p[i]; + for (int j = 1; j < m; ++j) { + f[i][j] = f[f[i][j - 1]][j - 1]; + } + for (var nxt : g[i]) { + int j = nxt[0], w = nxt[1]; + if (j != p[i]) { + p[j] = i; + cnt[j] = cnt[i].clone(); + cnt[j][w]++; + depth[j] = depth[i] + 1; + q.offer(j); + } + } + } + int k = queries.length; + int[] ans = new int[k]; + for (int i = 0; i < k; ++i) { + int u = queries[i][0], v = queries[i][1]; + int x = u, y = v; + if (depth[x] < depth[y]) { + int t = x; + x = y; + y = t; + } + for (int j = m - 1; j >= 0; --j) { + if (depth[x] - depth[y] >= (1 << j)) { + x = f[x][j]; + } + } + for (int j = m - 1; j >= 0; --j) { + if (f[x][j] != f[y][j]) { + x = f[x][j]; + y = f[y][j]; + } + } + if (x != y) { + x = p[x]; + } + int mx = 0; + for (int j = 0; j < 26; ++j) { + mx = Math.max(mx, cnt[u][j] + cnt[v][j] - 2 * cnt[x][j]); + } + ans[i] = depth[u] + depth[v] - 2 * depth[x] - mx; + } + return ans; + } +} ``` ### **C++** ```cpp - +class Solution { +public: + vector minOperationsQueries(int n, vector>& edges, vector>& queries) { + int m = 32 - __builtin_clz(n); + vector> g[n]; + int f[n][m]; + int p[n]; + int cnt[n][26]; + int depth[n]; + memset(f, 0, sizeof(f)); + memset(cnt, 0, sizeof(cnt)); + memset(depth, 0, sizeof(depth)); + memset(p, 0, sizeof(p)); + for (auto& e : edges) { + int u = e[0], v = e[1], w = e[2] - 1; + g[u].emplace_back(v, w); + g[v].emplace_back(u, w); + } + queue q; + q.push(0); + while (!q.empty()) { + int i = q.front(); + q.pop(); + f[i][0] = p[i]; + for (int j = 1; j < m; ++j) { + f[i][j] = f[f[i][j - 1]][j - 1]; + } + for (auto& [j, w] : g[i]) { + if (j != p[i]) { + p[j] = i; + memcpy(cnt[j], cnt[i], sizeof(cnt[i])); + cnt[j][w]++; + depth[j] = depth[i] + 1; + q.push(j); + } + } + } + vector ans; + for (auto& qq : queries) { + int u = qq[0], v = qq[1]; + int x = u, y = v; + if (depth[x] < depth[y]) { + swap(x, y); + } + for (int j = m - 1; ~j; --j) { + if (depth[x] - depth[y] >= (1 << j)) { + x = f[x][j]; + } + } + for (int j = m - 1; ~j; --j) { + if (f[x][j] != f[y][j]) { + x = f[x][j]; + y = f[y][j]; + } + } + if (x != y) { + x = p[x]; + } + int mx = 0; + for (int j = 0; j < 26; ++j) { + mx = max(mx, cnt[u][j] + cnt[v][j] - 2 * cnt[x][j]); + } + ans.push_back(depth[u] + depth[v] - 2 * depth[x] - mx); + } + return ans; + } +}; ``` ### **Go** ```go - +func minOperationsQueries(n int, edges [][]int, queries [][]int) []int { + m := bits.Len(uint(n)) + g := make([][][2]int, n) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m) + } + p := make([]int, n) + cnt := make([][26]int, n) + cnt[0] = [26]int{} + depth := make([]int, n) + for _, e := range edges { + u, v, w := e[0], e[1], e[2]-1 + g[u] = append(g[u], [2]int{v, w}) + g[v] = append(g[v], [2]int{u, w}) + } + q := []int{0} + for len(q) > 0 { + i := q[0] + q = q[1:] + f[i][0] = p[i] + for j := 1; j < m; j++ { + f[i][j] = f[f[i][j-1]][j-1] + } + for _, nxt := range g[i] { + j, w := nxt[0], nxt[1] + if j != p[i] { + p[j] = i + cnt[j] = [26]int{} + for k := 0; k < 26; k++ { + cnt[j][k] = cnt[i][k] + } + cnt[j][w]++ + depth[j] = depth[i] + 1 + q = append(q, j) + } + } + } + ans := make([]int, len(queries)) + for i, qq := range queries { + u, v := qq[0], qq[1] + x, y := u, v + if depth[x] < depth[y] { + x, y = y, x + } + for j := m - 1; j >= 0; j-- { + if depth[x]-depth[y] >= (1 << j) { + x = f[x][j] + } + } + for j := m - 1; j >= 0; j-- { + if f[x][j] != f[y][j] { + x, y = f[x][j], f[y][j] + } + } + if x != y { + x = p[x] + } + mx := 0 + for j := 0; j < 26; j++ { + mx = max(mx, cnt[u][j]+cnt[v][j]-2*cnt[x][j]) + } + ans[i] = depth[u] + depth[v] - 2*depth[x] - mx + } + return ans +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} ``` ### **...** diff --git a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README_EN.md b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README_EN.md index 6da91c35cab9d..76de25ef910bb 100644 --- a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README_EN.md +++ b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/README_EN.md @@ -64,25 +64,271 @@ For each queries[i], it can be shown that answer[i] is the minimum number of ope ### **Python3** ```python - +class Solution: + def minOperationsQueries( + self, n: int, edges: List[List[int]], queries: List[List[int]] + ) -> List[int]: + m = n.bit_length() + g = [[] for _ in range(n)] + f = [[0] * m for _ in range(n)] + p = [0] * n + cnt = [None] * n + depth = [0] * n + for u, v, w in edges: + g[u].append((v, w - 1)) + g[v].append((u, w - 1)) + cnt[0] = [0] * 26 + q = deque([0]) + while q: + i = q.popleft() + f[i][0] = p[i] + for j in range(1, m): + f[i][j] = f[f[i][j - 1]][j - 1] + for j, w in g[i]: + if j != p[i]: + p[j] = i + cnt[j] = cnt[i][:] + cnt[j][w] += 1 + depth[j] = depth[i] + 1 + q.append(j) + ans = [] + for u, v in queries: + x, y = u, v + if depth[x] < depth[y]: + x, y = y, x + for j in reversed(range(m)): + if depth[x] - depth[y] >= (1 << j): + x = f[x][j] + for j in reversed(range(m)): + if f[x][j] != f[y][j]: + x, y = f[x][j], f[y][j] + if x != y: + x = p[x] + mx = max(cnt[u][j] + cnt[v][j] - 2 * cnt[x][j] for j in range(26)) + ans.append(depth[u] + depth[v] - 2 * depth[x] - mx) + return ans ``` ### **Java** ```java - +class Solution { + public int[] minOperationsQueries(int n, int[][] edges, int[][] queries) { + int m = 32 - Integer.numberOfLeadingZeros(n); + List[] g = new List[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + int[][] f = new int[n][m]; + int[] p = new int[n]; + int[][] cnt = new int[n][0]; + int[] depth = new int[n]; + for (var e : edges) { + int u = e[0], v = e[1], w = e[2] - 1; + g[u].add(new int[] {v, w}); + g[v].add(new int[] {u, w}); + } + cnt[0] = new int[26]; + Deque q = new ArrayDeque<>(); + q.offer(0); + while (!q.isEmpty()) { + int i = q.poll(); + f[i][0] = p[i]; + for (int j = 1; j < m; ++j) { + f[i][j] = f[f[i][j - 1]][j - 1]; + } + for (var nxt : g[i]) { + int j = nxt[0], w = nxt[1]; + if (j != p[i]) { + p[j] = i; + cnt[j] = cnt[i].clone(); + cnt[j][w]++; + depth[j] = depth[i] + 1; + q.offer(j); + } + } + } + int k = queries.length; + int[] ans = new int[k]; + for (int i = 0; i < k; ++i) { + int u = queries[i][0], v = queries[i][1]; + int x = u, y = v; + if (depth[x] < depth[y]) { + int t = x; + x = y; + y = t; + } + for (int j = m - 1; j >= 0; --j) { + if (depth[x] - depth[y] >= (1 << j)) { + x = f[x][j]; + } + } + for (int j = m - 1; j >= 0; --j) { + if (f[x][j] != f[y][j]) { + x = f[x][j]; + y = f[y][j]; + } + } + if (x != y) { + x = p[x]; + } + int mx = 0; + for (int j = 0; j < 26; ++j) { + mx = Math.max(mx, cnt[u][j] + cnt[v][j] - 2 * cnt[x][j]); + } + ans[i] = depth[u] + depth[v] - 2 * depth[x] - mx; + } + return ans; + } +} ``` ### **C++** ```cpp - +class Solution { +public: + vector minOperationsQueries(int n, vector>& edges, vector>& queries) { + int m = 32 - __builtin_clz(n); + vector> g[n]; + int f[n][m]; + int p[n]; + int cnt[n][26]; + int depth[n]; + memset(f, 0, sizeof(f)); + memset(cnt, 0, sizeof(cnt)); + memset(depth, 0, sizeof(depth)); + memset(p, 0, sizeof(p)); + for (auto& e : edges) { + int u = e[0], v = e[1], w = e[2] - 1; + g[u].emplace_back(v, w); + g[v].emplace_back(u, w); + } + queue q; + q.push(0); + while (!q.empty()) { + int i = q.front(); + q.pop(); + f[i][0] = p[i]; + for (int j = 1; j < m; ++j) { + f[i][j] = f[f[i][j - 1]][j - 1]; + } + for (auto& [j, w] : g[i]) { + if (j != p[i]) { + p[j] = i; + memcpy(cnt[j], cnt[i], sizeof(cnt[i])); + cnt[j][w]++; + depth[j] = depth[i] + 1; + q.push(j); + } + } + } + vector ans; + for (auto& qq : queries) { + int u = qq[0], v = qq[1]; + int x = u, y = v; + if (depth[x] < depth[y]) { + swap(x, y); + } + for (int j = m - 1; ~j; --j) { + if (depth[x] - depth[y] >= (1 << j)) { + x = f[x][j]; + } + } + for (int j = m - 1; ~j; --j) { + if (f[x][j] != f[y][j]) { + x = f[x][j]; + y = f[y][j]; + } + } + if (x != y) { + x = p[x]; + } + int mx = 0; + for (int j = 0; j < 26; ++j) { + mx = max(mx, cnt[u][j] + cnt[v][j] - 2 * cnt[x][j]); + } + ans.push_back(depth[u] + depth[v] - 2 * depth[x] - mx); + } + return ans; + } +}; ``` ### **Go** ```go +func minOperationsQueries(n int, edges [][]int, queries [][]int) []int { + m := bits.Len(uint(n)) + g := make([][][2]int, n) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m) + } + p := make([]int, n) + cnt := make([][26]int, n) + cnt[0] = [26]int{} + depth := make([]int, n) + for _, e := range edges { + u, v, w := e[0], e[1], e[2]-1 + g[u] = append(g[u], [2]int{v, w}) + g[v] = append(g[v], [2]int{u, w}) + } + q := []int{0} + for len(q) > 0 { + i := q[0] + q = q[1:] + f[i][0] = p[i] + for j := 1; j < m; j++ { + f[i][j] = f[f[i][j-1]][j-1] + } + for _, nxt := range g[i] { + j, w := nxt[0], nxt[1] + if j != p[i] { + p[j] = i + cnt[j] = [26]int{} + for k := 0; k < 26; k++ { + cnt[j][k] = cnt[i][k] + } + cnt[j][w]++ + depth[j] = depth[i] + 1 + q = append(q, j) + } + } + } + ans := make([]int, len(queries)) + for i, qq := range queries { + u, v := qq[0], qq[1] + x, y := u, v + if depth[x] < depth[y] { + x, y = y, x + } + for j := m - 1; j >= 0; j-- { + if depth[x]-depth[y] >= (1 << j) { + x = f[x][j] + } + } + for j := m - 1; j >= 0; j-- { + if f[x][j] != f[y][j] { + x, y = f[x][j], f[y][j] + } + } + if x != y { + x = p[x] + } + mx := 0 + for j := 0; j < 26; j++ { + mx = max(mx, cnt[u][j]+cnt[v][j]-2*cnt[x][j]) + } + ans[i] = depth[u] + depth[v] - 2*depth[x] - mx + } + return ans +} +func max(a, b int) int { + if a > b { + return a + } + return b +} ``` ### **...** diff --git a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.cpp b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.cpp new file mode 100644 index 0000000000000..5aa801d2b50fe --- /dev/null +++ b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.cpp @@ -0,0 +1,67 @@ +class Solution { +public: + vector minOperationsQueries(int n, vector>& edges, vector>& queries) { + int m = 32 - __builtin_clz(n); + vector> g[n]; + int f[n][m]; + int p[n]; + int cnt[n][26]; + int depth[n]; + memset(f, 0, sizeof(f)); + memset(cnt, 0, sizeof(cnt)); + memset(depth, 0, sizeof(depth)); + memset(p, 0, sizeof(p)); + for (auto& e : edges) { + int u = e[0], v = e[1], w = e[2] - 1; + g[u].emplace_back(v, w); + g[v].emplace_back(u, w); + } + queue q; + q.push(0); + while (!q.empty()) { + int i = q.front(); + q.pop(); + f[i][0] = p[i]; + for (int j = 1; j < m; ++j) { + f[i][j] = f[f[i][j - 1]][j - 1]; + } + for (auto& [j, w] : g[i]) { + if (j != p[i]) { + p[j] = i; + memcpy(cnt[j], cnt[i], sizeof(cnt[i])); + cnt[j][w]++; + depth[j] = depth[i] + 1; + q.push(j); + } + } + } + vector ans; + for (auto& qq : queries) { + int u = qq[0], v = qq[1]; + int x = u, y = v; + if (depth[x] < depth[y]) { + swap(x, y); + } + for (int j = m - 1; ~j; --j) { + if (depth[x] - depth[y] >= (1 << j)) { + x = f[x][j]; + } + } + for (int j = m - 1; ~j; --j) { + if (f[x][j] != f[y][j]) { + x = f[x][j]; + y = f[y][j]; + } + } + if (x != y) { + x = p[x]; + } + int mx = 0; + for (int j = 0; j < 26; ++j) { + mx = max(mx, cnt[u][j] + cnt[v][j] - 2 * cnt[x][j]); + } + ans.push_back(depth[u] + depth[v] - 2 * depth[x] - mx); + } + return ans; + } +}; \ No newline at end of file diff --git a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.go b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.go new file mode 100644 index 0000000000000..1babb4d3725e7 --- /dev/null +++ b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.go @@ -0,0 +1,73 @@ +func minOperationsQueries(n int, edges [][]int, queries [][]int) []int { + m := bits.Len(uint(n)) + g := make([][][2]int, n) + f := make([][]int, n) + for i := range f { + f[i] = make([]int, m) + } + p := make([]int, n) + cnt := make([][26]int, n) + cnt[0] = [26]int{} + depth := make([]int, n) + for _, e := range edges { + u, v, w := e[0], e[1], e[2]-1 + g[u] = append(g[u], [2]int{v, w}) + g[v] = append(g[v], [2]int{u, w}) + } + q := []int{0} + for len(q) > 0 { + i := q[0] + q = q[1:] + f[i][0] = p[i] + for j := 1; j < m; j++ { + f[i][j] = f[f[i][j-1]][j-1] + } + for _, nxt := range g[i] { + j, w := nxt[0], nxt[1] + if j != p[i] { + p[j] = i + cnt[j] = [26]int{} + for k := 0; k < 26; k++ { + cnt[j][k] = cnt[i][k] + } + cnt[j][w]++ + depth[j] = depth[i] + 1 + q = append(q, j) + } + } + } + ans := make([]int, len(queries)) + for i, qq := range queries { + u, v := qq[0], qq[1] + x, y := u, v + if depth[x] < depth[y] { + x, y = y, x + } + for j := m - 1; j >= 0; j-- { + if depth[x]-depth[y] >= (1 << j) { + x = f[x][j] + } + } + for j := m - 1; j >= 0; j-- { + if f[x][j] != f[y][j] { + x, y = f[x][j], f[y][j] + } + } + if x != y { + x = p[x] + } + mx := 0 + for j := 0; j < 26; j++ { + mx = max(mx, cnt[u][j]+cnt[v][j]-2*cnt[x][j]) + } + ans[i] = depth[u] + depth[v] - 2*depth[x] - mx + } + return ans +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} \ No newline at end of file diff --git a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.java b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.java new file mode 100644 index 0000000000000..4b45ffed2c4e3 --- /dev/null +++ b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.java @@ -0,0 +1,67 @@ +class Solution { + public int[] minOperationsQueries(int n, int[][] edges, int[][] queries) { + int m = 32 - Integer.numberOfLeadingZeros(n); + List[] g = new List[n]; + Arrays.setAll(g, i -> new ArrayList<>()); + int[][] f = new int[n][m]; + int[] p = new int[n]; + int[][] cnt = new int[n][0]; + int[] depth = new int[n]; + for (var e : edges) { + int u = e[0], v = e[1], w = e[2] - 1; + g[u].add(new int[] {v, w}); + g[v].add(new int[] {u, w}); + } + cnt[0] = new int[26]; + Deque q = new ArrayDeque<>(); + q.offer(0); + while (!q.isEmpty()) { + int i = q.poll(); + f[i][0] = p[i]; + for (int j = 1; j < m; ++j) { + f[i][j] = f[f[i][j - 1]][j - 1]; + } + for (var nxt : g[i]) { + int j = nxt[0], w = nxt[1]; + if (j != p[i]) { + p[j] = i; + cnt[j] = cnt[i].clone(); + cnt[j][w]++; + depth[j] = depth[i] + 1; + q.offer(j); + } + } + } + int k = queries.length; + int[] ans = new int[k]; + for (int i = 0; i < k; ++i) { + int u = queries[i][0], v = queries[i][1]; + int x = u, y = v; + if (depth[x] < depth[y]) { + int t = x; + x = y; + y = t; + } + for (int j = m - 1; j >= 0; --j) { + if (depth[x] - depth[y] >= (1 << j)) { + x = f[x][j]; + } + } + for (int j = m - 1; j >= 0; --j) { + if (f[x][j] != f[y][j]) { + x = f[x][j]; + y = f[y][j]; + } + } + if (x != y) { + x = p[x]; + } + int mx = 0; + for (int j = 0; j < 26; ++j) { + mx = Math.max(mx, cnt[u][j] + cnt[v][j] - 2 * cnt[x][j]); + } + ans[i] = depth[u] + depth[v] - 2 * depth[x] - mx; + } + return ans; + } +} \ No newline at end of file diff --git a/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.py b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.py new file mode 100644 index 0000000000000..364c2e6e429b3 --- /dev/null +++ b/solution/2800-2899/2846.Minimum Edge Weight Equilibrium Queries in a Tree/Solution.py @@ -0,0 +1,43 @@ +class Solution: + def minOperationsQueries( + self, n: int, edges: List[List[int]], queries: List[List[int]] + ) -> List[int]: + m = n.bit_length() + g = [[] for _ in range(n)] + f = [[0] * m for _ in range(n)] + p = [0] * n + cnt = [None] * n + depth = [0] * n + for u, v, w in edges: + g[u].append((v, w - 1)) + g[v].append((u, w - 1)) + cnt[0] = [0] * 26 + q = deque([0]) + while q: + i = q.popleft() + f[i][0] = p[i] + for j in range(1, m): + f[i][j] = f[f[i][j - 1]][j - 1] + for j, w in g[i]: + if j != p[i]: + p[j] = i + cnt[j] = cnt[i][:] + cnt[j][w] += 1 + depth[j] = depth[i] + 1 + q.append(j) + ans = [] + for u, v in queries: + x, y = u, v + if depth[x] < depth[y]: + x, y = y, x + for j in reversed(range(m)): + if depth[x] - depth[y] >= (1 << j): + x = f[x][j] + for j in reversed(range(m)): + if f[x][j] != f[y][j]: + x, y = f[x][j], f[y][j] + if x != y: + x = p[x] + mx = max(cnt[u][j] + cnt[v][j] - 2 * cnt[x][j] for j in range(26)) + ans.append(depth[u] + depth[v] - 2 * depth[x] - mx) + return ans