寻找一个图中所有的关键边,关键边的定义是:如果这个边去除,那么所有节点就不能都到达了(不连通)。譬如在上图中,[1, 3]这条边是关键边。
可以使用Tarjan Algorithm来解决这个这个问题:https://www.youtube.com/watch?v=thLQYBlz2DM
基本的思路是,使用两个数组: dic 和 low来分别存储 节点访问的顺序 和 当前节点所有相邻节点中dic最低的节点(不包括direct 父节点)
class Solution:
def criticalConnections(self, n: int, connections: List[List[int]]) -> List[List[int]]:
#使用两个数组来保存每个节点的 dic, low(编号, 它能连接的除了根节点的最小节点的编号)
#首先在dfs的时候让 dic 和 low 都按顺序增长,当所有递归返回时,将low值变为该节点所有的相连节点中 最小的dict值(除了考虑与它相连的根节点)。
#遍历所有list,check是不是其中一个点的low值大于另一个点的dic值(因为只有没改变过low的节点会发生这种情况)
map1 = {} #使用一个map来存储边
for val in connections:
if map1.get(val[0]) == None:
map1[val[0]] = [val[1]]
else:
map1[val[0]].append(val[1])
if map1.get(val[1]) == None:
map1[val[1]] = [val[0]]
else:
map1[val[1]].append(val[0])
dic = [None for _ in range(len(map1.keys()))] #初始化dic
low = [None for _ in range(len(map1.keys()))] #初始化low
count = 1
def oneStep(ptr, pre):
nonlocal count #使用一个全局变量来初始化low 和 dic
low[ptr] = count
dic[ptr] = count
for val in map1[ptr]:#dfs所有没有访问过的相邻节点
if low[val] == None:
count += 1
oneStep(val, ptr)
#After traversing all the nodes, reset the low value to be the lowest one in the adjacent nodes' dic values
temp = dic[ptr]
for val in map1[ptr]:
if pre != None and val != pre: # except the direct father's value
temp = min(temp, low[val])
low[ptr] = temp
oneStep(0, None)
print(dic, low)
#print(dic, low)
result = []
for edge in connections:# traverse every edge, if the low[a] > dic[b] or low[b] > dic[b], then this edge is one of the critical edges.
a = edge[0]
b = edge[1]
if low[a] > dic[b] or low[b] > dic[a] :
result.append([a, b])
return result