查看: 2068| 回复: 11
跳转到指定楼层
上一主题 下一主题
收起左侧

[树/链表/图] detect cycle in DFS

🔗
匿名用户-4JYU8  2021-6-29 15:14:27 |倒序浏览

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
突然发现自己并不理解 为什么需要3个状态 而不是2个状态 visited 0/1 去判断directed graph有没有cycle 呀 ? 这里我肯定漏了什么,
有没有什么反例?  谢谢

```
    bool findCycle(int current,const vector<vector<int>>& graph, vector<int>&visited){
        if(visited[current]){
            return false;
        }
        visited[current]=true;
        for(const int& next_node: graph[current]){
            if(!findCycle(next_node,graph,visited)){
                return false;
            }
        }
        visited[current]=false;
        return true;

    }
```

评分

参与人数 1大米 +1 收起 理由
pikailun + 1 赞一个

查看全部评分


上一篇:大家有什么有效二刷的方法?
下一篇:这不是国人干的好事吧?
推荐
maristie 2021-6-29 18:46:40 | 只看该作者
全局:
本帖最后由 maristie 于 2021-6-29 18:52 编辑

简单来说,3个状态分别代表
1. 仍在调用栈上的节点
2. 未访问的节点
3. 已访问且退出调用栈的节点

当且仅当遇到1类节点时,图是cyclic的。
往细了说不完,建议LZ参考CLRS的22.3。DFS往深了考可以很难,所以我觉得还是有必要系统学习一下的。
p.s. LZ的代码举个反例,想象一个菱形,从左顶点分别经由上下顶点到右顶点(相当于2个stream),这种情况是acyclic的,但LZ的代码会判断成cyclic。

评分

参与人数 4大米 +6 收起 理由
不知道小帅 + 1 赞一个
pikailun + 1 赞一个
aodeyyoyo + 1 赞一个
14417335 + 3

查看全部评分

回复

使用道具 举报

推荐
timzyt 2021-8-1 14:04:47 | 只看该作者
全局:
您好楼主,我看其他答主的答案都很完善了,想提供另外一种思路。
其实cycle detection 可以用BFS-based topological sort来实现。

对图跑一遍topological sort然后看遍历的节点数量是否等于图的节点数量。

https://www.geeksforgeeks.org/de ... ed-graph-using-bfs/
回复

使用道具 举报

全局:
maristie 发表于 2021-6-29 18:46
简单来说,3个状态分别代表
1. 仍在调用栈上的节点
2. 未访问的节点

感谢回复,我演练了一下你说的菱形的栗子感觉用这个代码是可以判断的呀,当扫到最下面的节点D时,已经到头,没有孩子节点可以遍历了, 所以会恢复它的visited[i]->false, 然后从头再继续遍历,希望指正问题,谢谢。 btw 上面的代码true or false 好像写反了
      
A -> B
|       |
V      V
C - >D

```
    bool findCycle(int current,const vector<vector<int>>& graph, vector<int>&visited){
        if(visited[current]){
            return false;
        }
        visited[current]=true;
        for(const int& next_node: graph[current]){
            if(findCycle(next_node,graph,visited)){
                return true;
            }
        }
        visited[current]=false;
        return false;

    }
```
回复

使用道具 举报

🔗
14417335 2021-6-29 23:09:47 | 只看该作者
全局:
没法给楼主加米.

"抱歉,您不能对匿名帖评分"
回复

使用道具 举报

全局:
可以想象有4个node 0,1,2,3
directed edge:

(0,1)
(0,2)
(2,1)
(2,3)

从0开始dfs,1没有后续child,mark 1 visited
然后进入2,2会走到1,发现1visited,然后就会误以为cycle
回复

使用道具 举报

🔗
youziwry 2021-6-30 03:11:49 | 只看该作者
全局:
martingalemsy 发表于 2021-6-30 02:17
感谢回复,我演练了一下你说的菱形的栗子感觉用这个代码是可以判断的呀,当扫到最下面的节点D时,已经到 ...

这段代码好像work,但肯定效率不高,因为你把访问过的点改为没访问过,下次就还要继续访问,你举的例子里,如果D能连向一个非常大的图里,那么A->B->D访问过后,A->C->D又要再访问一次
回复

使用道具 举报

🔗
woshiduga 2021-6-30 03:54:23 | 只看该作者
全局:
2个状态 3个状态都一样,2个状态就是会重复访问已经访问过的点
回复

使用道具 举报

🔗
martingalemsy 2021-6-30 04:29:31 | 只看该作者
全局:
youziwry 发表于 2021-6-30 03:11
这段代码好像work,但肯定效率不高,因为你把访问过的点改为没访问过,下次就还要继续访问,你举的例子里 ...

了解了,谢谢:D
回复

使用道具 举报

🔗
martingalemsy 2021-6-30 04:29:48 | 只看该作者
全局:
woshiduga 发表于 2021-6-30 03:54
2个状态 3个状态都一样,2个状态就是会重复访问已经访问过的点

了解了,谢谢:D
回复

使用道具 举报

🔗
cannoli 2021-6-30 07:35:09 | 只看该作者
全局:
dfs的时候把parent node一起传下去,每次loop遇到parent node就skip.
这样2个状态就够了.
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表