一、无向图:\green{一、无向图:}一、无向图:
目标:\red{目标:}目标:
- 找关节点
- 找关节点对应联通分量
- 找点或边的重联通分量
- 找割边
时间:邻接矩阵O(N^2)、邻接表O(E)
关节点:\red{关节点:}关节点:去掉该点后,剩余图不是个联通图,剩余联通图的数量为所求联通分量。
基本思想\red{基本思想}基本思想,采用一次DFS计算每个点在搜索树中的层级。
维护:
dfn[x]:表示点x在搜索树中搜索次序,依次递增
low[x]:表示点x必须通过子节点路径可以到达的最小层次(最祖先节点)。
subnets[x]:表示去掉点x后的联通图数量
充要条件:\red{充要条件:}充要条件:
- 若点x是DFS搜索树的根,则x有至少2个孩子时,x是关节点,联通数量为其孩子数量。
- 若点x非DFS搜索树的根,则x的孩子y,存在low[y] >= dfn[x],则x是关节点,联通数量为满足条件y的数量+1
解释:\red{解释:}解释:
- 若x为根,好理解,当x不是关节点时,DFS时,x一定最多有1个孩子。
- 若x非根,重点解释low[y]>=dfn[x],low[y]表示点y通过向下走的方式可以到达的最祖先的节点z,当这个z还没有x的层级小,即z不是x的祖先,则去掉x后,y不能联系到x的祖先,x是关节点。
如何维护low和dfn数组?\red{如何维护low和dfn数组?}如何维护low和dfn数组?
DFS向下搜索时,初始化dfn和low数组,dfn和low都等于搜索次序,以后dfn固定不变。
DFS回溯时,更新low数组,low在两种情况中取最小:
- 孩子中low最小的
- 邻接点中dfn最小的
割边:\red{割边:}割边:
当low[y] > dfn[x]时,xy边为割边
点重联通分量:\red{点重联通分量:}点重联通分量:
另行维护一个栈,DFS正向搜索时,把搜索树边和回边压入栈中,回溯时,若遇到关节点,则弹出边直到遇到关节点与其孩子的边,则这些边组成了一个重联通分量。
回边:非搜索树的边(非科学定义,可自行拓展)
边重联通分量:\red{边重联通分量:}边重联通分量:
去除割边后,剩下就是边联通图
二、有向图:\green{二、有向图:}二、有向图:
找有向图强联通分量