LC-882.细分图中的可到达节点
题目描述
给你一个无向图(原始图),图中有 n 个节点,编号从 0 到 n - 1 。你决定将图中的每条边 细分 为一条节点链,每条边之间的新节点数各不相同。
图用由边组成的二维数组 edges 表示,其中 edges[i] = [ui, vi, cnti] 表示原始图中节点 ui 和 vi 之间存在一条边,cnti 是将边 细分 后的新节点总数。注意,cnti == 0 表示边不可细分。
要 细分 边 [ui, vi] ,需要将其替换为 (cnti + 1) 条新边,和 cnti 个新节点。新节点为 x1, x2, …, xcnti ,新边为 [ui, x1], [x1, x2], [x2, x3], …, [xcnti+1, xcnti], [xcnti, vi] 。
现在得到一个 新的细分图 ,请你计算从节点 0 出发,可以到达多少个节点?如果节点间距离是 maxMoves 或更少,则视为 可以到达 。
给你原始图和 maxMoves ,返回 新的细分图中从节点 0 出发 可到达的节点数 。
示例1:
1 |
|
提示1:
1 |
|
Dijkstra 算法
将 $cnt_i$ 看成类似权值,再通过 Dijkstra 算法得到每个原始点到 $0$ 的最短路径即可。
需要注意的有两点:
- 计算距离的时候要使用 $cnt + 1$ ,因为还要加上原始节点的消耗。
- 得到最短路径后,计算
可达点
总数时需要将原始节点
和拆分节点
分开来计算避免重复计算原始点。对于原始节点,当 $d[i]$ 小于 $maxMoves$ 时,即为可达;而对于拆分节点,通过遍历所有边得出,对于某条边 $e(u, v)$ ,该边的可达的拆分点显然为经过 $u$ 点可达的拆分点与经过 $v$ 点可达的拆分点交集,设两者数量分别为 $u_x$ 和 $v_x$ 、该边拆分点总数为 $all$,那么该边可达的拆分点总数即为 $min(all, u_x + v_x)$ ,注意这里的 $min(all, )$ 相当于去了重。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
45class Solution {
public int reachableNodes(int[][] edges, int maxMoves, int n) {
// Build graph
List<int[]>[] g = new List[n];
Arrays.setAll(g, k -> new ArrayList());
for(int i = 0; i < edges.length; i++){
g[edges[i][0]].add(new int[]{edges[i][1], edges[i][2] + 1}); // +1, 因为还要算上原始点的距离
g[edges[i][1]].add(new int[]{edges[i][0], edges[i][2] + 1});
}
// dijkstra
PriorityQueue<int[]> min = new PriorityQueue<>((a, b) -> a[1] - b[1]);
min.offer(new int[]{0, 0});
int[] d = new int[n];
Arrays.fill(d, Integer.MAX_VALUE);
d[0] = 0;
Set<Integer> visit = new HashSet<>();
while(!min.isEmpty()){
int[] top = min.poll();
if(!visit.add(top[0])){
continue;
}
for(int[] p : g[top[0]]){
if(d[p[0]] > d[top[0]] + p[1]){
d[p[0]] = d[top[0]] + p[1]; // 对该点的所有出边执行松弛操作
min.offer(new int[]{p[0], d[p[0]]});
}
}
}
int ans = 0;
// 原始点和拆分点分开来算
for(int item : d){
if(item <= maxMoves){
ans++;
}
}
for(int[] e : edges){
int a = Math.max(0, maxMoves - d[e[0]]);
int b = Math.max(0, maxMoves - d[e[1]]);
ans += Math.min(e[2], a + b);
}
return ans;
}
}
LC-882.细分图中的可到达节点
https://wecgwm.github.io/2022/11/26/LC-882-细分图中的可到达节点/