算法 之 求解有向图和无向图的环的长度
文章目录
- 习题
- 2608.图中最短环
- 2360.图中的最长环
-
求解一个图中的,环的长度是一类比较经典的问题,当然
判断是否有环
就是更加基础一点的问题啦 -
求解环的
最大or最小长度
,其实我们可以采用BFS或者DFS
进行求解,下面我着重介绍这个无向图BFS
,有向图BFS
求解,同时要注意时间复杂度的问题 -
其实我们只需查看将要加入的
节点
的长度是否已经确定
,如果已经确定的话,说明这个节点已经不是第一次访问了
,那么就会出现一个环环的长度就是:dis[x] + dis[neigh] + 1
-
无向图中,需要遍历每一个起点的情况,并且还不能在
找到第一个环就返回
习题
2608.图中最短环
2608.图中最短环
- 无向图的情况,需要遍历每一个起点
- 观察时间复杂度,
每次的bfs都是o(m),每一个节点都遍历,那就是 o(n*m)
from collections import deque
class Solution:
def findShortestCycle(self, n: int, edges: List[List[int]]) -> int:
graph = [[] for _ in range(n)]
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
min_cycle = float('inf')
def bfs(start):
queue = deque([(start, -1)]) # (node, parent)
visited = {start: 0} # 记录节点到start的距离
ans = float("inf")
while queue:
x, fa = queue.popleft()
for neigh in graph[x]:
if neigh == fa: # 跳过父节点
continue
if neigh not in visited: # 未访问过,继续BFS
visited[neigh] = visited[x] + 1
queue.append((neigh, x))
else: # 发现环!
# 环长度 = x到start的距离 + neigh到start的距离 + 1
cycle_len = visited[x] + visited[neigh] + 1
ans = min(ans,cycle_len)
return ans
return float('inf') # 未找到环
for i in range(n):
cycle_len = bfs(i)
print(cycle_len)
min_cycle = min(min_cycle, cycle_len)
return min_cycle if min_cycle != float('inf') else -1
2360.图中的最长环
2360.图中的最长环
有向图
- 并且,注意到,一个节点只会
最多有一个出边
- 和上面的无向图的不同:如果还是采用这个
BFS
的话,也可以完成,但是时间复杂度会超时,但是下面展示一下DFS
的解法,只用遍历一遍o(n)
class Solution:
def longestCycle(self, edges: List[int]) -> int:
# 注意题目的条件,至多只有一条有向边,每次回溯的时候,可以记录当前的路径上的点
ans = -1
path = []
n = len(edges)
visited = [False]*n
def dfs(curi):
nonlocal ans
next = edges[curi]
if next != -1 :
# 接下来还能行走,如果没被访问,就加入
if not visited[next]:
visited[next] = True
path.append(next)
dfs(next)
else:
# 被访问过了,需要判断是否在路径中
if next in path:
cal = path.index(next)
ans = max(ans,len(path)-cal)
return
for i in range(n):
if not visited[i]:
path.clear()
path.append(i)
dfs(i)
return ans