leetcode

Leetcode Solutions (0x6A73)
git clone https://git.pngu.org/leetcode
Log | Files | Refs | Submodules | README

commit d259ffeae14d4188ca694380359526a86db802e2
parent a7a40439387a971340f709df793470c06b914a90
Author: Jack Sangdahl <jack@pngu.org>
Date:   Fri, 12 Jun 2026 14:25:56 -0600

3559. number of ways to assign edge weights 2

Diffstat:
Anum_ways_assign_edge_weight2.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Anum_ways_assign_edge_weight2.py | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 210 insertions(+), 0 deletions(-)

diff --git a/num_ways_assign_edge_weight2.c b/num_ways_assign_edge_weight2.c @@ -0,0 +1,137 @@ +// 3559. Number of Ways to Assign Edge Weights II +#include "leetcode.h" + +/* + * there is an undirected tree with 'n' nodes labeled from 1 to 'n', rooted at + * node 1. the tree is represented by a 2d integer array 'edges' of length 'n - + * 1', where 'edges[i] = [ui, vi]' indicates that there is an edge between nodes + * 'ui' and 'vi'. return an array 'answer' where 'answer[i]' is the number of + * valid assignments for 'queries[i]'. since the answer may be very large, apply + * modulo 10^9+7 to each 'answer[i]'. + */ + +struct node { + int val; + struct node *next; +}; + +void add_edge(struct node **adj, int u, int v) { + struct node *node = (struct node *)malloc(sizeof(struct node)); + node->val = v; + node->next = adj[u]; + adj[u] = node; +} + +int lca(int u, int v, int **up, int *depth, int log) { + if (depth[u] < depth[v]) { + int temp = u; + u = v; + v = temp; + } + int diff = depth[u] - depth[v]; + for (int k = 0; k < log; k++) { + if ((diff >> k) & 1) + u = up[k][u]; + } + if (u == v) + return u; + for (int k = log - 1; k >= 0; k--) + if (up[k][u] != up[k][v]) { + u = up[k][u]; + v = up[k][v]; + } + return up[0][u]; +} + +int *assignEdgeWeights(int **edges, int edgesSize, int *edgesColSize, + int **queries, int queriesSize, int *queriesColSize, + int *returnSize + +) { + int n = edgesSize + 1, mod = 1e9 + 7; + struct node **adj = (struct node **)calloc(n + 1, sizeof(struct node *)); + for (int i = 0; i < edgesSize; i++) { + int u = edges[i][0], v = edges[i][1]; + add_edge(adj, u, v); + add_edge(adj, v, u); + } + int *depth = (int *)calloc(n + 1, sizeof(int)); + int *parent = (int *)calloc(n + 1, sizeof(int)); + int *vis = (int *)calloc(n + 1, sizeof(int)); + int *queue = (int *)malloc((n + 1) * sizeof(int)); + int front = 0, back = 0; + queue[back++] = 1; + vis[1] = 1; + while (front < back) { + int node = queue[front++]; + for (struct node *cur = adj[node]; cur != NULL; cur = cur->next) { + int neighbour = cur->val; + if (!vis[neighbour]) { + vis[neighbour] = 1; + depth[neighbour] = depth[node] + 1; + parent[neighbour] = node; + queue[back++] = neighbour; + } + } + } + int log = 1; + while ((1 << log) <= n) + log++; + int **up = (int **)malloc(log * sizeof(int *)); + for (int k = 0; k < log; k++) + up[k] = (int *)calloc(n + 1, sizeof(int)); + for (int v = 0; v <= n; v++) + up[0][v] = parent[v]; + for (int k = 1; k < log; k++) + for (int v = 0; v <= n; v++) + up[k][v] = up[k - 1][up[k - 1][v]]; + int *pow2 = (int *)malloc((n + 1) * sizeof(int)); + pow2[0] = 1; + for (int i = 1; i <= n; i++) + pow2[i] = (long long)pow2[i - 1] * 2 % mod; + int *ans = (int *)malloc(queriesSize * sizeof(int)); + *returnSize = queriesSize; + for (int i = 0; i < queriesSize; i++) { + int u = queries[i][0], v = queries[i][1]; + int ancestor = lca(u, v, up, depth, log); + int dist = depth[u] + depth[v] - 2 * depth[ancestor]; + ans[i] = dist ? pow2[dist - 1] : 0; + } + return ans; +} + +int main() { + int e1i[1][2] = {{1, 2}}; + int q1i[2][2] = {{1, 1}, {1, 2}}; + int e2i[4][2] = {{1, 2}, {1, 3}, {3, 4}, {3, 5}}; + int q2i[3][2] = {{1, 4}, {3, 4}, {2, 5}}; + struct two_d_arr *e1 = + two_d_arr_init(ARRAY_SIZE(e1i), ARRAY_SIZE(e1i[0]), e1i); + struct two_d_arr *q1 = + two_d_arr_init(ARRAY_SIZE(q1i), ARRAY_SIZE(q1i[0]), q1i); + struct two_d_arr *e2 = + two_d_arr_init(ARRAY_SIZE(e2i), ARRAY_SIZE(e2i[0]), e2i); + struct two_d_arr *q2 = + two_d_arr_init(ARRAY_SIZE(q2i), ARRAY_SIZE(q2i[0]), q2i); + int rs1, r1[] = {0, 1}, rs2, r2[] = {2, 1, 4}; + int *aew1 = assignEdgeWeights(e1->arr, e1->row_size, e1->col_size, q1->arr, + q1->row_size, q1->col_size, &rs1); + int *aew2 = assignEdgeWeights(e2->arr, e2->row_size, e2->col_size, q2->arr, + q2->row_size, q2->col_size, &rs2); + for (int i = 0; i < rs1; i++) { + printf("%d ", aew1[i]); + assert(aew1[i] == r1[i]); + } + printf("\n"); + for (int i = 0; i < rs2; i++) { + printf("%d ", aew2[i]); + assert(aew2[i] == r2[i]); + } + printf("\n"); + free(aew1); + free(aew2); + two_d_arr_free(e1); + two_d_arr_free(q1); + two_d_arr_free(e2); + two_d_arr_free(q2); +} diff --git a/num_ways_assign_edge_weight2.py b/num_ways_assign_edge_weight2.py @@ -0,0 +1,73 @@ +# 3559. Number of Ways to Assign Edge Weights II + +""" +there is an undirected tree with 'n' nodes labeled from 1 to 'n', rooted at +node 1. the tree is represented by a 2d integer array 'edges' of length 'n - +1', where 'edges[i] = [ui, vi]' indicates that there is an edge between nodes +'ui' and 'vi'. return an array 'answer' where 'answer[i]' is the number of +valid assignments for 'queries[i]'. since the answer may be very large, apply +modulo 10^9+7 to each 'answer[i]'. +""" + + +class Solution: + def assignEdgeWeights( + self, edges: List[List[int]], queries: List[List[int]] + ) -> List[int]: + n, mod = len(edges) + 1, 10**9 + 7 + adj = [[] for _ in range(n + 1)] + for u, v in edges: + adj[u].append(v) + adj[v].append(u) + depth = [0] * (n + 1) + parent = [0] * (n + 1) + vis = [0] * (n + 1) + vis[1] = 1 + q = deque([1]) + while q: + node = q.popleft() + for neighbour in adj[node]: + if not vis[neighbour]: + vis[neighbour] = 1 + depth[neighbour] = depth[node] + 1 + parent[neighbour] = node + q.append(neighbour) + log = max(1, n.bit_length()) + up = [parent] + for k in range(1, log): + prev = up[-1] + up.append([prev[prev[v]] for v in range(n + 1)]) + + def lca(u, v): + if depth[u] < depth[v]: + u, v = v, u + diff = depth[u] - depth[v] + for k in range(log): + if (diff >> k) & 1: + u = up[k][u] + if u == v: + return u + for k in range(log - 1, -1, -1): + if up[k][u] != up[k][v]: + u = up[k][u] + v = up[k][v] + return up[0][u] + + pow2 = [1] * (n + 1) + for i in range(1, n + 1): + pow2[i] = pow2[i - 1] * 2 % mod + ans = [] + for u, v in queries: + k = depth[u] + depth[v] - 2 * depth[lca(u, v)] + ans.append(pow2[k - 1] if k else 0) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.assignEdgeWeights(edges=[[1, 2]], queries=[[1, 1], [1, 2]])) + print( + obj.assignEdgeWeights( + edges=[[1, 2], [1, 3], [3, 4], [3, 5]], queries=[[1, 4], [3, 4], [2, 5]] + ) + )