3419. 图的最大边权的最小值
给你两个整数 n
和 threshold
,同时给你一个 n
个节点的 有向 带权图,节点编号为 0
到 n - 1
。这个图用 二维 整数数组 edges
表示,其中 edges[i] = [Ai, Bi, Wi]
表示节点 Ai
到节点 Bi
之间有一条边权为 Wi
的有向边。
你需要从这个图中删除一些边(也可能 不 删除任何边),使得这个图满足以下条件:
threshold
条出去的边。请你返回删除必要的边后,最大 边权的 最小值 为多少。如果无法满足所有的条件,请你返回 -1 。
示例 1:
输入:n = 5, edges = [[1,0,1],[2,0,2],[3,0,1],[4,3,1],[2,1,1]], threshold = 2
输出:1
解释:
删除边 2 -> 0
。剩余边中的最大值为 1 。
示例 2:
输入:n = 5, edges = [[0,1,1],[0,2,2],[0,3,1],[0,4,1],[1,2,1],[1,4,1]], threshold = 1
输出:-1
解释:
无法从节点 2 到节点 0 。
示例 3:
输入:n = 5, edges = [[1,2,1],[1,3,3],[1,4,5],[2,3,2],[3,4,2],[4,0,1]], threshold = 1
输出:2
解释:
删除边 1 -> 3
和 1 -> 4
。剩余边中的最大值为 2 。
示例 4:
输入:n = 5, edges = [[1,2,1],[1,3,3],[1,4,5],[2,3,2],[4,0,1]], threshold = 1
输出:-1
提示:
2 <= n <= 105
1 <= threshold <= n - 1
1 <= edges.length <= min(105, n * (n - 1) / 2).
edges[i].length == 3
0 <= Ai, Bi < n
Ai != Bi
1 <= Wi <= 106
原站题解
java 解法, 执行用时: 100 ms, 内存消耗: 93.7 MB, 提交时间: 2025-01-15 09:34:10
class Solution { public int minMaxWeight(int n, int[][] edges, int threshold) { if (edges.length < n - 1) { return -1; } List<int[]>[] g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>()); for (int[] e : edges) { int x = e[0], y = e[1], w = e[2]; g[y].add(new int[]{x, w}); } int[] dis = new int[n]; Arrays.fill(dis, Integer.MAX_VALUE); dis[0] = 0; PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]); pq.offer(new int[]{0, 0}); // (路径最大边权, 节点编号) int ans = 0; while (!pq.isEmpty()) { int[] p = pq.poll(); int d = p[0], x = p[1]; if (d > dis[x]) { continue; } ans = d; n--; for (int[] e : g[x]) { int y = e[0]; int newD = Math.max(d, e[1]); if (newD < dis[y]) { dis[y] = newD; pq.offer(new int[]{newD, y}); } } } return n > 0 ? -1 : ans; } }
java 解法, 执行用时: 277 ms, 内存消耗: 101.3 MB, 提交时间: 2025-01-15 09:33:56
class Solution { public int minMaxWeight(int n, int[][] edges, int threshold) { if (edges.length < n - 1) { return -1; } List<int[]>[] g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>()); int maxW = 0; for (int[] e : edges) { int x = e[0], y = e[1], w = e[2]; g[y].add(new int[]{x, w}); maxW = Math.max(maxW, w); } int[] vis = new int[n]; int left = 0; int right = maxW + 1; while (left + 1 < right) { int mid = (left + right) >>> 1; if (dfs(0, mid, vis, g) == n) { right = mid; } else { left = mid; } } return right > maxW ? -1 : right; } private int dfs(int x, int upper, int[] vis, List<int[]>[] g) { vis[x] = upper; // 避免每次二分重新创建 vis 数组 int cnt = 1; for (int[] e : g[x]) { int y = e[0]; if (e[1] <= upper && vis[y] != upper) { cnt += dfs(y, upper, vis, g); } } return cnt; } }
cpp 解法, 执行用时: 254 ms, 内存消耗: 256 MB, 提交时间: 2025-01-15 09:33:21
class Solution { public: // 二分 + dfs int minMaxWeight(int n, vector<vector<int>>& edges, int) { if (edges.size() < n - 1) { return -1; } vector<vector<pair<int, int>>> g(n); int max_w = 0; for (auto& e : edges) { int x = e[0], y = e[1], w = e[2]; g[y].emplace_back(x, w); max_w = max(max_w, w); } vector<int> vis(n); auto check = [&](int upper) -> bool { int left = n; auto dfs = [&](this auto&& dfs, int x) -> void { vis[x] = upper; // 避免每次二分重新创建 vis 数组 left--; for (auto& [y, w] : g[x]) { if (w <= upper && vis[y] != upper) { dfs(y); } } }; dfs(0); return left == 0; }; int left = 0, right = max_w + 1; while (left + 1 < right) { int mid = left + (right - left) / 2; (check(mid) ? right : left) = mid; } return right > max_w ? -1 : right; } // dijkstra 算法 int minMaxWeight2(int n, vector<vector<int>>& edges, int) { if (edges.size() < n - 1) { return -1; } vector<vector<pair<int, int>>> g(n); for (auto& e : edges) { int x = e[0], y = e[1], w = e[2]; g[y].emplace_back(x, w); } vector<int> dis(n, INT_MAX); dis[0] = 0; priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq; pq.emplace(0, 0); // (路径最大边权, 节点编号) while (!pq.empty()) { auto [d, x] = pq.top(); pq.pop(); if (d > dis[x]) { continue; } for (auto& [y, w] : g[x]) { int new_d = max(d, w); if (new_d < dis[y]) { dis[y] = new_d; pq.emplace(new_d, y); } } } int ans = ranges::max(dis); return ans == INT_MAX ? -1 : ans; } };
golang 解法, 执行用时: 99 ms, 内存消耗: 23.9 MB, 提交时间: 2025-01-15 09:32:14
// 二分 + dfs func minMaxWeight1(n int, edges [][]int, _ int) int { if len(edges) < n-1 { return -1 } type edge struct{ to, w int } g := make([][]edge, n) maxW := 0 for _, e := range edges { x, y, w := e[0], e[1], e[2] g[y] = append(g[y], edge{x, w}) maxW = max(maxW, w) } vis := make([]int, n) ans := 1 + sort.Search(maxW, func(upper int) bool { upper++ left := n var dfs func(int) dfs = func(x int) { vis[x] = upper // 避免每次二分重新创建 vis 数组 left-- for _, e := range g[x] { if e.w <= upper && vis[e.to] != upper { dfs(e.to) } } } dfs(0) return left == 0 }) if ans > maxW { return -1 } return ans } // dijkstra 算法 func minMaxWeight(n int, edges [][]int, _ int) int { if len(edges) < n-1 { return -1 } type edge struct{ to, w int } g := make([][]edge, n) for _, e := range edges { x, y, w := e[0], e[1], e[2] g[y] = append(g[y], edge{x, w}) } dis := make([]int, n) for i := range dis { dis[i] = math.MaxInt } dis[0] = 0 h := hp{{}} for len(h) > 0 { p := heap.Pop(&h).(pair) x := p.x d := p.dis if d > dis[x] { continue } for _, e := range g[x] { y := e.to newD := max(d, e.w) if newD < dis[y] { dis[y] = newD heap.Push(&h, pair{newD, y}) } } } ans := slices.Max(dis) if ans == math.MaxInt { return -1 } return ans } type pair struct{ dis, x int } // 路径最大边权, 节点编号 type hp []pair func (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].dis < h[j].dis } func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *hp) Push(v any) { *h = append(*h, v.(pair)) } func (h *hp) Pop() (v any) { a := *h; *h, v = a[:len(a)-1], a[len(a)-1]; return }
python3 解法, 执行用时: 1878 ms, 内存消耗: 64.2 MB, 提交时间: 2025-01-15 09:31:08
class Solution: # 二分+dfs def minMaxWeight(self, n: int, edges: List[List[int]], _: int) -> int: if len(edges) < n - 1: return -1 g = [[] for _ in range(n)] for x, y, w in edges: g[y].append((x, w)) vis = [0] * n def check(upper: int) -> bool: def dfs(x: int) -> int: vis[x] = upper # 避免每次二分重新创建 vis 数组 cnt = 1 for y, w in g[x]: if w <= upper and vis[y] != upper: cnt += dfs(y) return cnt return dfs(0) == n max_w = max(e[2] for e in edges) ans = bisect_left(range(max_w + 1), True, 1, key=check) return -1 if ans > max_w else ans # dijkstra 算法 def minMaxWeight2(self, n: int, edges: List[List[int]], _: int) -> int: if len(edges) < n - 1: return -1 g = [[] for _ in range(n)] for x, y, w in edges: g[y].append((x, w)) dis = [inf] * n dis[0] = 0 h = [(0, 0)] # (路径最大边权, 节点编号) while h: d, x = heappop(h) if d > dis[x]: continue for y, w in g[x]: new_d = max(d, w) if new_d < dis[y]: dis[y] = new_d heappush(h, (new_d, y)) ans = max(dis) return -1 if ans == inf else ans