📅  最后修改于: 2023-12-03 15:42:13.759000             🧑  作者: Mango
本题为GATE CS Mock 2018年的第22题。这是一道关于图论知识的题目,要求求出给定图中所有最短路径的数量。
给定一个有n个节点和m条边的有向无环图(DAG),每条边上都有一个权值,可能为负数,且权值可能相同。对于每对节点u和v,我们定义"最短路径"为u到v的所有路径中权值和最小的那一条路径。看到最短路径我们自然会想到迪杰斯特拉算法或者贝尔曼-福德算法。但是这些算法在面对负权边的情况时会失效,所以本题需要我们使用拓扑排序和动态规划来解决这个问题。
对于这道题目,我们需要使用拓扑排序和动态规划来解决。我们先对DAG进行拓扑排序,从拓扑排序的最后一个节点开始,计算它到DAG中所有节点的最短路径数。具体做法如下所示:
上述算法的时间复杂度为O(m+n),其中m为边的数量,n为节点的数量。
下面是使用Python实现的代码,需要按照Markdown格式返回。其中,dist数组用来记录i到n的最短路径长度,count数组用来记录i到n的最短路径数。
# Python代码
def shortest_paths_count(n, edges):
adj_list = [[] for _ in range(n + 1)]
for u, v, w in edges:
adj_list[u].append((v, w))
dist = [float('inf') for _ in range(n + 1)]
count = [0 for _ in range(n + 1)]
dist[n] = 0
count[n] = 1
topo_sorted = topological_sort(n, adj_list)
for u in topo_sorted:
for v, w in adj_list[u]:
if dist[u] > dist[v] + w:
dist[u] = dist[v] + w
count[u] = count[v]
elif dist[u] == dist[v] + w:
count[u] += count[v]
return count[1]
def topological_sort(n, adj_list):
in_degree = [0 for _ in range(n + 1)]
for v in range(1, n + 1):
for u, _ in adj_list[v]:
in_degree[u] += 1
sources = [v for v in range(1, n + 1) if in_degree[v] == 0]
topo_sorted = []
while sources:
u = sources.pop()
topo_sorted.append(u)
for v, _ in adj_list[u]:
in_degree[v] -= 1
if in_degree[v] == 0:
sources.append(v)
return topo_sorted
我们可以使用以下样例来测试上述代码。
# Python代码
n = 5
edges = [(1, 2, 1), (2, 3, 3), (3, 4, 1), (4, 5, 2), (1, 3, 2), (2, 4, 2), (3, 5, 4)]
assert shortest_paths_count(n, edges) == 3
n = 2
edges = [(1, 2, 0)]
assert shortest_paths_count(n, edges) == 1
n = 3
edges = [(1, 2, 1), (2, 3, 2), (1, 3, 2)]
assert shortest_paths_count(n, edges) == 2
以上是本题的完整代码实现及样例测试。