network_recovery_pathways.c (4572B)
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 138 139 140 141 142 143 144 145 | // 3620. Network Recovery Pathways #include "leetcode.h" /* * you are given a directed acyclic graph of 'n' nodes numbered from 0 to 'n - * 1'.this is represented by a 2d array 'edges' of length 'm', where 'edges[i] = * [ui, vi, costi]' indicates a one-way communication from node 'ui' to node * 'vi' with a recovery of 'costi'. some nodes may be offline. you are given a * boolean array where 'online[i] = true' means node 'i' is online. a path from * to 0 to 'n - 1' is valid if all intermediate nodes on the path are online, * and the total recovery cost of all edges on the path does not exceed 'k'. * return the maximum path score among all valid paths. if no valid path exists, * return -1. */ struct edge { int to; int weight; struct edge *next; }; struct heap_node { long long cost; int node; }; void add_edge(struct edge **graph, int from, int to, int weight) { struct edge *e = (struct edge *)malloc(sizeof(struct edge)); e->to = to; e->weight = weight; e->next = graph[from]; graph[from] = e; } void swap_heap(struct heap_node *a, struct heap_node *b) { struct heap_node tmp = *a; *a = *b; *b = tmp; } void push(struct heap_node *heap, int *size, struct heap_node node) { heap[++(*size)] = node; int i = *size; while (i > 1 && heap[i].cost < heap[i / 2].cost) { swap_heap(&heap[i], &heap[i / 2]); i /= 2; } } struct heap_node pop(struct heap_node *heap, int *size) { struct heap_node top = heap[1]; heap[1] = heap[(*size)--]; int i = 1; while (i * 2 <= *size) { int j = i * 2; if (j + 1 <= *size && heap[j + 1].cost < heap[j].cost) j++; if (heap[i].cost <= heap[j].cost) break; swap_heap(&heap[i], &heap[j]); i = j; } return top; } bool check(int min_weight, struct edge **graph, bool *online, int n, long long k, int heap_capacity) { struct heap_node *heap = (struct heap_node *)malloc((heap_capacity + 5) * sizeof(struct heap_node)); int heap_size = 0; long long *best_cost = (long long *)malloc(n * sizeof(long long)); memset(best_cost, -1, n * sizeof(long long)); push(heap, &heap_size, (struct heap_node){0, 0}); while (heap_size > 0) { struct heap_node curr = pop(heap, &heap_size); long long curr_cost = curr.cost; int curr_node = curr.node; if (curr_node == n - 1) { free(heap); free(best_cost); return true; } if (best_cost[curr_node] != -1 && best_cost[curr_node] <= curr_cost) continue; best_cost[curr_node] = curr_cost; for (struct edge *e = graph[curr_node]; e != NULL; e = e->next) { int next_node = e->to, edge_weight = e->weight; if (curr_cost + edge_weight > k) continue; if (!online[next_node]) continue; if (edge_weight < min_weight) continue; push(heap, &heap_size, (struct heap_node){curr_cost + edge_weight, next_node}); } } free(heap); free(best_cost); return false; } int findMaxPathScore(int **edges, int edgesSize, int *edgesColSize, bool *online, int onlineSize, long long k) { int max_weight = 0; struct edge **graph = (struct edge **)calloc(onlineSize, sizeof(struct edge *)); for (int i = 0; i < edgesSize; i++) { int from_node = edges[i][0]; int to_node = edges[i][1]; int weight = edges[i][2]; add_edge(graph, from_node, to_node, weight); max_weight = fmax(weight, max_weight); } int left = -1, right = max_weight + 1; while (left <= right) { int mid = (left + right) / 2; if (check(mid, graph, online, onlineSize, k, edgesSize + onlineSize + 5)) left = mid + 1; else right = mid - 1; } return right >= 0 ? right : -1; } int main() { int e1i[4][3] = {{0, 1, 5}, {1, 3, 10}, {0, 2, 3}, {2, 3, 4}}; int e2i[6][3] = {{0, 1, 7}, {1, 4, 5}, {0, 2, 6}, {2, 3, 6}, {3, 4, 2}, {2, 4, 6}}; bool o1[] = {true, true, true, true}, o2[] = {true, true, true, false, true}; struct two_d_arr *e1 = two_d_arr_init(ARRAY_SIZE(e1i), ARRAY_SIZE(e1i[0]), e1i); struct two_d_arr *e2 = two_d_arr_init(ARRAY_SIZE(e2i), ARRAY_SIZE(e2i[0]), e2i); int r1 = findMaxPathScore(e1->arr, e1->row_size, e1->col_size, o1, ARRAY_SIZE(o1), 10); int r2 = findMaxPathScore(e2->arr, e2->row_size, e2->col_size, o2, ARRAY_SIZE(o2), 12); printf("%d\n", r1); assert(r1 == 3); printf("%d\n", r2); assert(r2 == 6); two_d_arr_free(e1); two_d_arr_free(e2); } |