有向无环图的每个节点通过的路径个数

记一道计算有向无环图的每个节点通过的路径个数的题目

菜鸡不会什么高级的方法,还希望有更好的方式解这道题。

题目

给定一张有向无环图,图中包含n个节点和m条有向边,每个节点都标有一个唯一的整数编号,从1~n,我们定义经过一个节点的路径是指包含该节点的路径,且该路径可以反包含零条边(即路径只包含节点本身)。
样例一:
5 4
1 2
1 3
2 4
3 5
输出:
5
4
4
3
3
样例 二:
3 3
1 2
1 2
2 3
输出:
5
6
4

分析解释

对于样例一
在这里插入图片描述
输出的解释
节点1有5条路径经过它:1, 1->2, 1->3, 1->2->4, 1->3->5。
节点2有4条路径经过它:2, 1->2, 1->2->4, 2->4。
节点3有4条路径经过它:3, 1->3, 1->3->5, 3->5。
节点4有3条路径经过它:4, 1->2->4, 2->4。
节点5有3条路径经过它:5, 1->3->5, 3->5。
样例二:
在这里插入图片描述
输出的解释:
(1指向2的两条路径认为是两个)
节点1有5条路径经过它:1, 1->2, 1->2, 1->2->3, 1->2->3。
节点2有6条路径经过它:2, 1->2, 1->2, 1->2->3, 1->2->3,2->3。
节点3有4条路径经过它:3, 2->3, 1->2->3, 1->2->3。

代码

# 定义函数count_paths,接受边的列表edges和节点总数n作为参数
def count_paths(edges, n):
    # 初始化一个字典graph表示图,键为节点,值为与其相连的节点列表
    graph = {i: [] for i in range(1, n + 1)}
    # 初始化一个列表count记录每个节点的路径数量,初始为0
    count = [0 for i in range(n + 1)]
    # 初始化一个字符串列表strlist用于存储DFS过程中生成的路径字符串
    strlist = []
    # 初始化一个空字符串str2用于拼接路径
    str2 = ''
    
    # 根据输入的边列表构造图
    for u, v in edges:
        graph[u].append(v)
    
    # 对于图中的每个节点执行深度优先搜索并统计路径
    for node in range(1, n + 1):
        dfs(graph, node, strlist, str2)  # 执行DFS
        tongji(node, strlist, count)  # 统计路径数量
    
    # 返回除第一个节点外的所有节点的路径数量(因为第一个节点默认为0,无需计算)
    return count[1:]

# 定义深度优先搜索函数dfs,递归地遍历图
def dfs(graph, node, strlist, str2):
    # 构造当前节点的路径字符串并添加到strlist中
    str1 = str2 + str(node)
    strlist.append(str1)
    # 遍历与当前节点相连的所有节点,继续进行深度优先搜索
    for i in graph[node]:
        dfs(graph, i, strlist, str1)

# 定义统计函数tongji,计算以node为起点在strlist中出现的路径数量
def tongji(node, list, count):
    for i in list:
        # 如果节点存在于路径中,则增加该节点的路径计数
        if str(node) in i:
            count[node] += 1

# 主程序部分:读取输入,处理数据,调用count_paths函数并打印结果
n, m = list(map(int, input().split()))  # 读取节点数n和边数m
edges = []  # 初始化边的列表
for i in range(m):  # 根据边数m读取每一条边
    list1 = list(map(int, input().split()))  # 读取一条边的两个节点
    edges.append(list1)  # 将这条边添加到edges列表中
#print(edges)  # (这行是调试用的,可删除或注释)
print(count_paths(edges, n))  # 调用count_paths函数并输出结果
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值