题目描述
给定一个正整数 n
,表示一个 索引从 0 开始的有向加权 图的节点数量,以及一个 索引从 0 开始的二维数组 edges
,其中 edges[i] = [ui, vi, wi]
表示从节点 ui
到节点 vi
的一条权重为 wi
的边。
并给定一个节点 s
和一个节点数组 marked
;你的任务是找到从 s
到 marked
中 任何 节点的 最短 距离。
返回一个整数,表示从 s
到 marked
中任何节点的最短距离,如果从 s 到任何标记节点没有路径,则返回 -1
。
示例 1:
输入:n = 4, edges = [[0,1,1],[1,2,3],[2,3,2],[0,3,4]], s = 0, marked = [2,3]
输出:4
解释:从节点 0(绿色节点)到节点 2(红色节点)有一条路径,即 0->1->2,距离为 1 + 3 = 4。
从节点 0 到节点 3(红色节点)有两条路径,即 0->1->2->3 和 0->3,分别距离为 1 + 3 + 2 = 6 和 4。
它们中的最小值是 4。
示例 2:
输入:n = 5, edges = [[0,1,2],[0,2,4],[1,3,1],[2,3,3],[3,4,2]], s = 1, marked = [0,4]
输出:3
解释:从节点 1(绿色节点)到节点 0(红色节点)没有路径。
从节点 1 到节点 4(红色节点)有一条路径,即 1->3->4,距离为 1 + 2 = 3。
因此答案是 3。
示例 3:
输入:n = 4, edges = [[0,1,1],[1,2,3],[2,3,2]], s = 3, marked = [0,1]
输出:-1
解释:从节点 3(绿色节点)到任何一个标记节点(红色节点)都没有路径,因此答案是 -1。
提示:
2 <= n <= 500
1 <= edges.length <= 104
edges[i].length = 3
0 <= edges[i][0], edges[i][1] <= n - 1
1 <= edges[i][2] <= 106
1 <= marked.length <= n - 1
0 <= s, marked[i] <= n - 1
s != marked[i]
- 如果
i != j
则 marked[i] != marked[j]
- 图中可能有 重复的边 。
- 图的生成不会出现 自环 。
解法
方法一:Dijkstra 算法
我们先根据题目中提供的边的信息,建立一个邻接矩阵 $g$,其中 $g[i][j]$ 表示节点 $i$ 到节点 $j$ 的距离,如果不存在这样的边,则 $g[i][j]$ 为正无穷。
然后我们就可以使用 Dijkstra 算法求出从起点 $s$ 到所有节点的最短距离,记为 $dist$。
最后我们遍历所有的标记节点,找到距离最小的标记节点,如果距离为正无穷,则返回 $-1$。
时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为节点数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | class Solution:
def minimumDistance(
self, n: int, edges: List[List[int]], s: int, marked: List[int]
) -> int:
g = [[inf] * n for _ in range(n)]
for u, v, w in edges:
g[u][v] = min(g[u][v], w)
dist = [inf] * n
vis = [False] * n
dist[s] = 0
for _ in range(n):
t = -1
for j in range(n):
if not vis[j] and (t == -1 or dist[t] > dist[j]):
t = j
vis[t] = True
for j in range(n):
dist[j] = min(dist[j], dist[t] + g[t][j])
ans = min(dist[i] for i in marked)
return -1 if ans >= inf else ans
|
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 | class Solution {
public int minimumDistance(int n, List<List<Integer>> edges, int s, int[] marked) {
final int inf = 1 << 29;
int[][] g = new int[n][n];
for (var e : g) {
Arrays.fill(e, inf);
}
for (var e : edges) {
int u = e.get(0), v = e.get(1), w = e.get(2);
g[u][v] = Math.min(g[u][v], w);
}
int[] dist = new int[n];
Arrays.fill(dist, inf);
dist[s] = 0;
boolean[] vis = new boolean[n];
for (int i = 0; i < n; ++i) {
int t = -1;
for (int j = 0; j < n; ++j) {
if (!vis[j] && (t == -1 || dist[t] > dist[j])) {
t = j;
}
}
vis[t] = true;
for (int j = 0; j < n; ++j) {
dist[j] = Math.min(dist[j], dist[t] + g[t][j]);
}
}
int ans = inf;
for (int i : marked) {
ans = Math.min(ans, dist[i]);
}
return ans >= inf ? -1 : ans;
}
}
|
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 | class Solution {
public:
int minimumDistance(int n, vector<vector<int>>& edges, int s, vector<int>& marked) {
const int inf = 1 << 29;
vector<vector<int>> g(n, vector<int>(n, inf));
vector<int> dist(n, inf);
dist[s] = 0;
vector<bool> vis(n);
for (auto& e : edges) {
int u = e[0], v = e[1], w = e[2];
g[u][v] = min(g[u][v], w);
}
for (int i = 0; i < n; ++i) {
int t = -1;
for (int j = 0; j < n; ++j) {
if (!vis[j] && (t == -1 || dist[t] > dist[j])) {
t = j;
}
}
vis[t] = true;
for (int j = 0; j < n; ++j) {
dist[j] = min(dist[j], dist[t] + g[t][j]);
}
}
int ans = inf;
for (int i : marked) {
ans = min(ans, dist[i]);
}
return ans >= inf ? -1 : ans;
}
};
|
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 | func minimumDistance(n int, edges [][]int, s int, marked []int) int {
const inf = 1 << 29
g := make([][]int, n)
dist := make([]int, n)
for i := range g {
g[i] = make([]int, n)
for j := range g[i] {
g[i][j] = inf
}
dist[i] = inf
}
dist[s] = 0
for _, e := range edges {
u, v, w := e[0], e[1], e[2]
g[u][v] = min(g[u][v], w)
}
vis := make([]bool, n)
for _ = range g {
t := -1
for j := 0; j < n; j++ {
if !vis[j] && (t == -1 || dist[j] < dist[t]) {
t = j
}
}
vis[t] = true
for j := 0; j < n; j++ {
dist[j] = min(dist[j], dist[t]+g[t][j])
}
}
ans := inf
for _, i := range marked {
ans = min(ans, dist[i])
}
if ans >= inf {
return -1
}
return ans
}
|
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 | function minimumDistance(n: number, edges: number[][], s: number, marked: number[]): number {
const inf = 1 << 29;
const g: number[][] = Array(n)
.fill(0)
.map(() => Array(n).fill(inf));
const dist: number[] = Array(n).fill(inf);
const vis: boolean[] = Array(n).fill(false);
for (const [u, v, w] of edges) {
g[u][v] = Math.min(g[u][v], w);
}
dist[s] = 0;
for (let i = 0; i < n; ++i) {
let t = -1;
for (let j = 0; j < n; ++j) {
if (!vis[j] && (t == -1 || dist[t] > dist[j])) {
t = j;
}
}
vis[t] = true;
for (let j = 0; j < n; ++j) {
dist[j] = Math.min(dist[j], dist[t] + g[t][j]);
}
}
let ans = inf;
for (const i of marked) {
ans = Math.min(ans, dist[i]);
}
return ans >= inf ? -1 : ans;
}
|