num_ways_assign_edge_weight2.c (4247B)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 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); } |