Python 计算图(graph)中每个节点构成的环,统计每个节点环的个数,图计算,异构图统计子图环的数目,graph统计节点环的代码实战

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

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

医学小达人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值