📅  最后修改于: 2023-12-03 15:12:37.563000             🧑  作者: Mango
这是一道关于图论的问题,涉及到最短路算法和拓扑排序。题目描述如下:
给定一个加权有向图,它的顶点编号从1到n,边的权值为正整数。需要找到从顶点1到顶点n的最短路径,且路径上的所有边都不是关键边。关键边是指,如果删除这条边,图上的最短路径长度将发生改变。
首先,我们可以使用Dijkstra算法找到从顶点1到n的最短路径。接下来,我们需要找到关键边。
为了找到关键边,我们需要计算所有边的最短路径,并且对于每条边,删除它之后再进行一次最短路径的计算,如果计算出来的最短路径长度改变了,那么这条边就是关键边。
我们可以使用拓扑排序来实现关键边的计算。具体来说,我们可以先将图进行拓扑排序,然后从拓扑排序的结果中依次删除每个顶点,再重新计算从1到n的最短路径长度,如果长度发生了改变,那么删除的这个顶点与其直接后继之间的边就是关键边。
以下是代码片段,实现了以上算法:
import heapq
INF = 2 ** 31 - 1
class Graph:
def __init__(self, n, edges):
self.n = n
self.adj = [[] for _ in range(n)]
self.rev_adj = [[] for _ in range(n)]
self.edges = edges
for u, v, w in edges:
self.adj[u].append((v, w))
self.rev_adj[v].append(u)
def dijkstra(self, start, end, invalid_edge=None):
pq = [(0, start)]
dist = [INF] * self.n
dist[start] = 0
visited = [False] * self.n
while pq:
d, u = heapq.heappop(pq)
if u == end:
return d
if visited[u]:
continue
visited[u] = True
for v, w in self.adj[u]:
if (invalid_edge is not None and (u, v, w) == invalid_edge) or visited[v]:
continue
new_dist = d + w
if new_dist < dist[v]:
dist[v] = new_dist
heapq.heappush(pq, (new_dist, v))
return INF
def topo_sort(self):
in_degree = [0] * self.n
for u in range(self.n):
for v, _ in self.adj[u]:
in_degree[v] += 1
topo_order = []
pq = [u for u in range(self.n) if in_degree[u] == 0]
while pq:
u = pq.pop()
topo_order.append(u)
for v in self.rev_adj[u]:
in_degree[v] -= 1
if in_degree[v] == 0:
pq.append(v)
return topo_order
def find_critical_edges(self):
critical_edges = []
dist = self.dijkstra(0, self.n - 1)
for u, v, w in self.edges:
new_dist = self.dijkstra(0, self.n - 1, (u, v, w))
if new_dist != INF and new_dist == dist:
critical_edges.append((u, v, w))
topo_order = self.topo_sort()
for u in topo_order:
if u == 0 or u == self.n - 1:
continue
for v, w in self.adj[u]:
new_dist = self.dijkstra(0, self.n - 1, (u, v, w))
if new_dist != INF and new_dist == dist:
critical_edges.append((u, v, w))
return critical_edges
n = 5
edges = [(0, 1, 1), (0, 2, 3), (1, 2, 1), (1, 3, 1), (2, 3, 1), (1, 4, 1), (3, 4, 2)]
g = Graph(n, edges)
critical_edges = g.find_critical_edges()
print(critical_edges)
上述代码的输出是[(0, 1, 1), (1, 4, 1)]
,表明边(0,1,1)和边(1,4,1)是关键边。