182-小朋友崇拜圈-蓝桥云课-Python版代码解析

182-小朋友崇拜圈-蓝桥云课-Python版代码解析

原题链接:182-小朋友崇拜圈-蓝桥云课

标签:蓝桥杯, 思维, 图上dfs,2018,省赛

语言整理

一个有向图,每个节点u有且仅有一条出边u→v。给定g数组, g[u] = v 表示这条出边。求图中最长环的长度图示

思路

  • dfs(u) 表示当前访问节点 u ,集合 s 表示访问过的节点集
  • 如果 u 在 s 中,说明找到了完整的环
  • 如果 u 不在 s 中,添加到集合之中,并且访问后续节点 dfs(g[u])
  • 遍历所有节点,确保考虑到所有的联通分量

由以上思路得到的类似代码

s = set()
def dfs(u):
    if u in s: return #找到了换,本循环结束
    s.add(u)
    dfs(g[u])
for u in range(n+1):
    dfs(u)

问题如何求解环的长度?(不明白就画画图,u的大小肯定不能代表环的长度)

解决办法

  • 时间戳思想,额外记录每次访问节点 u 的序号 idx ,用字典存放 u:idx键值对(而前面用的 s 只能记录在不在,不能记录第几个(即来到的“时间”))
  • 如果 u 在 d 之中,说明第二次访问到 u,构成闭环。两次序号之差 idx - d[u]即环的长度
  • 如果 u 不在 d 中,则添加到字典中,并且访问后续节点 dfs([u],idx + 1)
  • 遍历所有节点,确保考虑所有连通分量
  • 在外层用res记录最大环长

Python代码答案与分析

import sys
input = lambda: sys.stdin.readline().strip()
sys.setrecursionlimit(10000)  #增加递归深度至少大于n,因为python默认只有1000
n = int(input())
g = [0] + list(map(int, input().split()))
res = 0
d = {}
def dfs(u, idx):
    global res
    if d.get(u) is not None: #非空,说明已记录,即找到了环,本循环结束
        res = max(res, idx - d[u])
        return 
    d[u] = idx #记录本次时间戳
    dfs(g[u], idx + 1)

for u in range(n+1): #确保访问所有连通分量
    dfs(u, 1)

print(res)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值