1.在图graph中,统计每个节点环的个数
def count_cycles(graph):
def dfs(node, start, visited):
visited[node] = True
count = 0
for neighbor in graph[node]:
if not visited[neighbor]:
count += dfs(neighbor, start, visited)
elif neighbor == start:
count += 1
return count
num_nodes = len(graph)
cycle_counts = [0] * num_nodes
for node in range(num_nodes):
visited = [False] * num_nodes
cycle_counts[node] = dfs(node, node, visited)
return cycle_counts
# 例子图示
graph = {
0: [1, 2],
1: [0, 2],
2: [0, 1, 3],
3: [2, 4],
4: [3]
}
cycle_counts = count_cycles(graph)
for node, count in enumerate(cycle_counts):
print(f"节点 {node} 的环个数:{count}")
思路:深度优先搜索,dfs
起始参数:当前 所在的节点node,这个路径的起始节点start,以及所有节点是否被visit过;
代码思路:从当前节点开始,首先visit【node】状态更改;其次遍历这个节点node的邻居节点,判断邻居节点是否是开始的start节点,如果是说明成环了,数目count += 1,如果不是start并且没有被visit过,那么产生dfs分支,继续搜索邻居的邻居;注意,在这里如果既不等于start,又被visit了,直接跳过去就好(即什么也不操作),说明这个节点不能成环的。
2.在图graph中,输出每个节点环的路径
就是每个节点所能组成的环有哪些
def find_cycles_in_graph(graph):
def dfs(node, start, path, visited, cycles):
if node in path and node == start and len(path) > 2:
cycles[start].append(path.copy())
return
if visited[node]:
return
visited[node] = True
path.append(node)
for neighbor in graph[node]:
if neighbor != start or len(path) > 1:
dfs(neighbor, start, path, visited, cycles)
path.pop()
visited[node] = False
cycles = {node: [] for node in graph}
for start_node in graph:
visited = {node: False for node in graph}
dfs(start_node, start_node, [], visited, cycles)
# 处理得到的环去掉重复项,因为环可能会被多次找到
for node, cyc in cycles.items():
unique_cycles = []
for cycle in cyc:
cycle.sort()
if cycle not in unique_cycles:
unique_cycles.append(cycle)
cycles[node] = unique_cycles
return cycles
# 示例图
graph = {
0: [1, 2],
1: [0, 2],
2: [0, 1, 3],
3: [2, 4],
4: [3, 1]
}
# 找出每个节点的环
cycles = find_cycles_in_graph(graph)
for node, cyc in cycles.items():
print(f"节点 {node} 参与的环有: {cyc}")
注意:这个代码是有bug的,就是去重完之后发现路径path中的节点被排序了,这样就丧失原来的路径了,所以我做了以下修改;
import copy
def find_cycles_in_graph(graph):
def dfs(node, start, path, visited, cycles):
if node in path and node == start and len(path) > 2:
cycles[start].append(path.copy())
return
if visited[node]:
return
visited[node] = True
path.append(node)
for neighbor in graph[node]:
if neighbor != start or len(path) > 1:
dfs(neighbor, start, path, visited, cycles)
path.pop()
visited[node] = False
cycles = {node: [] for node in graph}
for start_node in graph:
visited = {node: False for node in graph}
dfs(start_node, start_node, [], visited, cycles)
# 处理得到的环去掉重复项,因为环可能会被多次找到
for node, cyc in cycles.items():
unique_cycles = []
res_quchong = []
for cycle in cyc:
tmp_c = copy.deepcopy(cycle)
tmp_c.sort()
if tmp_c not in unique_cycles:
unique_cycles.append(tmp_c)
res_quchong.append(cycle)
cycles[node] = res_quchong
return cycles
# 示例图
graph = {
0: [1, 2],
1: [0, 2],
2: [0, 1, 3],
3: [2, 4],
4: [3, 1]
}
# 找出每个节点的环
cycles = find_cycles_in_graph(graph)
for node, cyc in cycles.items():
print(f"节点 {node} 参与的环有: {cyc}")
这样输出的环,即为每个节点的不重复路径path