虽然暂时用不到,还是花时间学习了一下,看网上玩ACM的大牛们都在做图论的题目,我也眼红了。。。
因为需要用到求强连通分量来判断AOE/PERT中的环路,先研究研究无向图的双连通分量。
对今天的学习做个总结:
无向图的连通分支(连通子图): 判断一个无向图是否连通,如果进行dfs或者bfs之后,还有未访问到的顶点,说明不是连通图,否则连通。
求解无向图的所有连通分支: 只需要重复调用dfs或者bfs 就可以解决:遍历顶点,如果v 未访问,则对其进行dfs, 然后标记访问。过程如下:
1 void dfs(int v){
2 node_pointer w;
3 visited[v] = TRUE;
4 for(w = graph[v]; w; w = w->link) {
5 if(!visited[w->vertex])
6 dfs(w->vertex);
7 }
8 }
9 void connect(){
10 int i;
11 for(i = 0; i < n; i++)
12 if(!visited[i]) {
13 dfs(i);
14 }
15 }
关节点(割点): 是图中一个顶点v, 如果删除它以及它关联的边后,得到的新图至少包含两个连通分支。
双连通图: 没有关节点的连通图。
连通无向图的双连通分支(双连通子图,块) : 是图G中一个最大双连通子图。
利用深度优先搜索dfs 可以求解双连通分支,因为dfs过程中,必定要经过关节点,并生成一棵深度优先搜索树。 而图G的连通子图必然是深搜树的一部分。
这张图很难看。 它有4个关节点:1,3,4,7, 将 图分为6个双连通分支。
如果以顶点3开始深搜,得到如下一棵树:
3是树根, 红色标号是 深度搜索访问节点的顺序, 红色边是图中深度搜索没有访问到的边(因为有的顶点可以多个边到达,深搜只要通过一个边到达顶点,就不再访问该顶点了),称作非树边,也就是树中没有的。 黑色的边是树边。
如果两个顶点u,v ,其中u是v的祖先或者v是u的祖先,那么非树边(u,v)叫做回退边。在深搜树中,所有的非树边都是回退边。 无向图的深搜树是一棵开放树,如果在其中添加一条回退边,就会形成环,该环路或扩大连通分量的范围,或者导致新的连通分量产生。
通过这个过程,可