classSolution: defnetworkDelayTime(self, times: List[List[int]], n: int, k: int) -> int: g = [[] for _ inrange(n)] for x, y, d in times: g[x - 1].append((y - 1, d)) dis = [inf] * n dis[k - 1] = 0 h = [(0, k - 1)] while h: dx, x = heappop(h) if dx > dis[x]: continue for y, d in g[x]: new_dis = dx + d if new_dis < dis[y]: dis[y] = new_dis heappush(h, (new_dis, y)) mx = max(dis) return mx if mx < inf else -1
defshortestPath(self, node1: int, node2: int) -> int: n = len(self.g) dis = [inf] * n dis[node1] = 0 h = [(0, node1)] while h: dx, x = heappop(h) if dx > dis[x]: continue for y, d in self.g[x]: new_dis = dx + d if new_dis < dis[y]: dis[y] = new_dis heappush(h, (new_dis, y)) return dis[node2] if dis[node2] < inf else -1
classSolution: defmaxProbability(self, n: int, edges: List[List[int]], succProb: List[float], start_node: int, end_node: int) -> float: g = [[] for _ inrange(n)] for i, (a, b) inenumerate(edges): g[a].append((b, succProb[i])) g[b].append((a, succProb[i])) dis = [0] * n dis[start_node] = 1 h = [(-1, start_node)] while h: dx, x = heappop(h) dx = -dx if dx < dis[x]: continue for y, d in g[x]: new_dis = dx * d if new_dis > dis[y]: dis[y] = new_dis heappush(h, (-new_dis, y)) return dis[end_node]
1631. Path With Minimum Effort
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defminimumEffortPath(self, heights: List[List[int]]) -> int: m, n = len(heights), len(heights[0]) h = [(0, 0, 0)] dis = [[inf] * n for _ inrange(m)] dis[0][0] = 0 while h: d, x, y = heappop(h) if x == m - 1and y == n - 1: return d if d > dis[x][y]: continue for nx, ny in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]: if0 <= nx < m and0 <= ny < n: new_dis = max(d, abs(heights[nx][ny] - heights[x][y])) if new_dis < dis[nx][ny]: dis[nx][ny] = new_dis heappush(h, (new_dis, nx, ny)) return -1
1368. Minimum Cost to Make at Least One Valid Path in a Grid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defminCost(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) dis = [[inf] * n for _ inrange(m)] dis[0] h = [(0, 0, 0)] while h: d, x, y = heappop(h) if x == m - 1and y == n - 1: return d for num, (nx, ny) inzip([1, 2, 3, 4], [(x, y + 1), (x, y - 1), (x + 1, y), (x - 1, y)]): if0 <= nx < m and0 <= ny < n: new_dis = d if num == grid[x][y] else d + 1 if new_dis < dis[nx][ny]: dis[nx][ny] = new_dis heappush(h, (new_dis, nx, ny))
1786. Number of Restricted Paths From First to Last Node
classSolution: defcountRestrictedPaths(self, n: int, edges: List[List[int]]) -> int: g = [[] for _ inrange(n + 1)] for x, y, d in edges: g[x].append((y, d)) g[y].append((x, d)) dis = [inf] * (n + 1) dis[n] = 0 h = [(0, n)] while h: dx, x = heappop(h) if dx > dis[x]: continue for y, d in g[x]: new_dis = dx + d if new_dis < dis[y]: dis[y] = new_dis heappush(h, (new_dis, y)) if dis[1] == inf: return0 mem = {n:1} mod = 10**9 + 7 defdfs(root): if root in mem: return mem[root] mem[root] = 0 for v, _ in g[root]: if dis[root] > dis[v]: mem[root] = (mem[root] + dfs(v)) % mod return mem[root] return dfs(1)
classSolution: defcountPaths(self, n: int, roads: List[List[int]]) -> int: g = [[] for _ inrange(n)] for x, y, d in roads: g[x].append((y, d)) g[y].append((x, d)) dis = [inf] * n dis[0] = 0 f = [0] * n f[0] = 1 h = [(0, 0)] whileTrue: dx, x = heappop(h) if x == n - 1: return f[-1] if dx > dis[x]: continue for y, d in g[x]: new_dis = dx + d if new_dis < dis[y]: dis[y] = new_dis f[y] = f[x] heappush(h, (new_dis, y)) elif new_dis == dis[y]: f[y] = (f[y] + f[x]) % 1_000_000_007
2662. Minimum Cost of a Path With Special Roads
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defminimumCost(self, start: List[int], target: List[int], specialRoads: List[List[int]]) -> int: t = tuple(target) dis = defaultdict(lambda: inf) dis[tuple(start)] = 0 vis = set() whileTrue: v, dv = None, -1 for p, d in dis.items(): if p notin vis and (dv < 0or d < dv): v, dv = p, d if v == t: return dv vis.add(v) vx, vy = v dis[t] = min(dis[t], dv + t[0] - vx + t[1] - vy) for x1, y1, x2, y2, cost in specialRoads: w = (x2, y2) dis[w] = min(dis[w], dv + abs(x1 - vx) + abs(y1 - vy) + cost)
classSolution: defsecondMinimum(self, n: int, edges: List[List[int]], time: int, change: int) -> int: g = [[] for _ inrange(n + 1)] for x, y in edges: g[x].append(y) g[y].append(x) dis = [[inf] * 2for _ inrange(n + 1)] dis[1][0] = 0 q = deque([(1, 0)]) while dis[n][1] == inf: x, dx = q.popleft() for y in g[x]: d = dx + 1 if d < dis[y][0]: dis[y][0] = d q.append((y, d)) elif dis[y][0] < d < dis[y][1]: dis[y][1] = d q.append((y, d)) ans = 0 for _ inrange(dis[n][1]): if ans % (change * 2) >= change: ans += change * 2 - ans % (change * 2) ans += time return ans
classSolution: defreachableNodes(self, edges: List[List[int]], maxMoves: int, n: int) -> int: g = [[] for _ inrange(n)] for u, v, cnt in edges: g[u].append((v, cnt + 1)) g[v].append((u, cnt + 1)) dis = self.dijkstra(g, 0) ans = sum(d <= maxMoves for d in dis) for u, v, cnt in edges: a = max(maxMoves - dis[u], 0) b = max(maxMoves - dis[v], 0) ans += min(a + b, cnt) return ans
defdijkstra(self, g: List[List[Tuple[int]]], start: int) -> List: dis = [inf] * len(g) dis[start] = 0 h = [(0, start)] while h: dx, x = heappop(h) if dx > dis[x]: continue for y, w in g[x]: new_dis = dis[x] + w if new_dis < dis[y]: dis[y] = new_dis heappush(h, (new_dis, y)) return dis
2203. Minimum Weighted Subgraph With the Required Paths
classSolution: defminimumWeight(self, n: int, edges: List[List[int]], src1: int, src2: int, dest: int) -> int: defdijkstra(g: List[List[Tuple[int]]], start: int) -> List[int]: dis = [inf] * n dis[start] = 0 h = [(0, start)] while h: dx, x = heappop(h) if dx > dis[x]: continue for y, w in g[x]: new_dis = dis[x] + w if new_dis < dis[y]: dis[y] = new_dis heappush(h, (new_dis, y)) return dis g = [[] for _ inrange(n)] rg = [[] for _ inrange(n)] for x, y, w in edges: g[x].append((y, w)) rg[y].append((x, w))
classSolution: defminimumTime(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) if grid[0][1] > 1and grid[1][0] > 1: return -1# no wait, no way. dis = [[inf] * n for _ inrange(m)] dis[0][0] = 0 h = [(0, 0, 0)] while h: d, x, y = heappop(h) if d > dis[x][y]: continue if x == m - 1and y == n - 1: return d for nx, ny in [[x - 1, y], [x + 1, y], [x, y - 1], [x, y + 1]]: if0 <= nx < m and0 <= ny < n: new_dis = max(d + 1, grid[nx][ny]) new_dis += (new_dis - nx - ny) % 2# parity contraint. if new_dis < dis[nx][ny]: dis[nx][ny] = new_dis heappush(h, (new_dis, nx, ny))
classSolution: defmodifiedGraphEdges(self, n: int, edges: List[List[int]], source: int, destination: int, target: int) -> List[List[int]]: g = [[] for _ inrange(n)] for i, (x, y, _) inenumerate(edges): g[x].append((y, i)) g[y].append((x, i)) dis = [[inf, inf] for _ inrange(n)] dis[source] = [0, 0]
defdijkstra(k: int) -> None: vis = [False] * n whileTrue: x = -1 for y, (b, d) inenumerate(zip(vis, dis)): ifnot b and (x < 0or d[k] < dis[x][k]): x = y if x == destination: return vis[x] = True for y, eid in g[x]: wt = edges[eid][2] if wt == -1: wt = 1 if k == 1and edges[eid][2] == -1: w = delta + dis[y][0] - dis[x][1] if w > wt: edges[eid][2] = wt = w dis[y][k] = min(dis[y][k], dis[x][k] + wt)
dijkstra(0) delta = target - dis[destination][0] if delta < 0: return [] dijkstra(1) if dis[destination][1] < target: return [] for e in edges: if e[2] == -1: e[2] = 1 return edges