热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

强连通分量+Tarjia+缩点

Tarjan貌似跟Hopcroft都是Cornell的大神。总的来说,Tarjan算法基于一个观察,即:同处于一个SCC中的结点必然构成DFS树的一棵子树。我们要找SCC,就得找到它在DFS树上的

Tarjan貌似跟Hopcroft都是Cornell的大神。总的来说, Tarjan算法基于一个观察,即:同处于一个SCC中的结点必然构成DFS树的一棵子树。 我们要找SCC,就得找到它在DFS树上的根。

那么怎么找呢?

考虑一下,如果DFS访问到了某个结点u,又顺着u来到了结点v, 但从v发出了一条反向边,指向了u的前驱w,那根据DFS的性质, u->v->w->u构成了一个环。这一堆东西必然处于同一个SCC。 所以某个要找到SCC子树的根,就得找那个在DFS树中最早被发现的结点,且这个结点要与它的一堆后继结点形成环。

这时候DFS的特性就派上用场了。最早发现的结点可以通过记录发现时间来实现,而反向边的判断可以通过结点颜色,即访问状态来实现。 定义一个结点的low值为:从该节点的子树结点可达的,尚未求出属于哪个SCC的结点的最早访问时间。 由于SCC构成子树,所以求没求出某个结点所在的SCC用栈来刻画就可以了: 每次访问到一个结点u,记录发现时间visit,并将它推到栈里去。 如果从u可达的结点v没访问过,那么访问v,用v的low值更新u; 否则,如果v已访问过,那就看看它在不在栈中。如果在,说明还没确定v到底属于哪个SCC, 这时(u, v)就是一条反向边了,根据v的visit值,更新u的low值即可。 最后回到u结点时,如果u的low值和visit相等了,显然u就是我们要找的根节点了。 从栈里把u和其上所有结点弹出来,这一堆东西就在一个SCC里了。

https://blog.csdn.net/sdsy191553/article/details/79674201

看的我迷迷糊糊的


推荐阅读
author-avatar
勇敢的刺鸟宝贝4164053383
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有