6.1 ADT图
定义:图G由两个集合组成:一个由顶点构成的有穷非空集合和一个由边构成的有穷允空集合.V(G)和E(G)分别表示图G的顶点集和边集,有时也用G=(V,E)表示图.
无向图是表示边的两个顶点之间没有次序关系的图.例如,顶点对(v0,v1)和(v1,v0)表示同一条边.
有向图是表示边的顶点对有方向的图.例如,顶点对<v0,v1>和<v1,v0>为不同的边.
图的限制:
1) 图中不能有从顶点i到其自身的边.
2) 同一条边在图中不能出现两次或两次以上,不满足这个限制的图称为多重图.
一些基本的概念:
1. 路径的长度:路径上边的条数
2. 简单路径:路径上除了起点和终点可能相同外,其余顶点都互不相同,可以用顶点序列来表示一条简单路径.
3. 回路(环路):一条简单路径,且其起点和终点相同.
4. 顶点的度:关联于该顶点的边的条数.
6.2 图的基本操作
深度优先搜索
下面是我写的第一个程序,但是是错误的,我调试的时候才发现,分配的内存空间是局部变量,所以进行:
dfs( 0, visited, graph);
时候,graph内部的数据均被销毁.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VERTICES 50 typedef struct NODE{ int vertex; struct NODE *link; }Node; void initNode( Node *graph[] ) { struct NODE node0_0, node0_1, node0_2, node1_1, node1_0, node1_3, node1_4, node2_2, node2_0, node2_5, node2_6; struct NODE node3_3, node3_1, node3_7, node4_4, node4_1, node4_7, node5_5, node5_2, node5_7; struct NODE node6_6, node6_2, node6_7, node7_7, node7_3, node7_4, node7_5, node7_6; node0_0.vertex = node1_0.vertex = node2_0.vertex = 0; node0_1.vertex = node1_1.vertex = node3_1.vertex = node4_1.vertex = 1; node0_2.vertex = node2_2.vertex = node5_2.vertex = node6_2.vertex = 2; node1_3.vertex = node3_3.vertex = node7_3.vertex = 3; node1_4.vertex = node4_4.vertex = node7_4.vertex = 4; node2_5.vertex = node5_5.vertex = node7_5.vertex = 5; node2_6.vertex = node6_6.vertex = node7_6.vertex = 6; node3_7.vertex = node4_7.vertex = node5_7.vertex = node6_7.vertex = node7_7.vertex = 7; node0_0.link = &node0_1; node0_1.link = &node0_2; node0_2.link = NULL; graph[ 0 ] = &node0_0; node1_1.link = &node1_0; node1_0.link = &node1_3; node1_3.link = &node1_4; node1_4.link = NULL; graph[ 1 ] = &node1_1; node2_2.link = &node2_0; node2_0.link = &node2_5; node2_5.link = &node2_6; node2_6.link = NULL; graph[ 2 ] = &node2_2; node3_3.link = &node3_1; node3_1.link = &node3_7; node3_7.link = NULL; graph[ 3 ] = &node3_3; node4_4.link = &node4_1; node4_1.link = &node4_7; node4_7.link = NULL; graph[ 4 ] = &node4_4; node5_5.link = &node5_2; node5_2.link = &node5_7; node5_7.link = NULL; graph[ 5 ] = &node5_5; node6_6.link = &node6_2; node6_2.link = &node6_7; node6_7.link = NULL; graph[ 6 ] = &node6_6; node7_7.link = &node7_3; node7_3.link = &node7_4; node7_4.link = &node7_5; node7_5.link = &node7_6; node7_6.link = NULL; graph[ 7 ] = &node7_7; } void dfs( int v, int *visited, Node *graph[] ) { Node *w = ( Node * )malloc( sizeof( Node ) ); visited[ v ] = 1; printf("%5d", v ); for ( w = graph[ v ]; w; w = w->link ){ if ( !visited[ w->vertex ] ){ dfs( w->vertex, visited, graph ); } } } int main( void ) { Node *graph[ MAX_VERTICES ]; int visited[ MAX_VERTICES ]; memset( visited, 0, sizeof( int ) * MAX_VERTICES ); memset( graph, 0, sizeof( Node * ) * MAX_VERTICES ); initNode( graph ); dfs( 0, visited, graph); return 0; }
那么应该怎么办呢?方法1是动态分配内存,但是什么时候free着实让我着急啊.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VERTICES 50 typedef struct NODE{ int vertex; struct NODE *link; }Node; void initNode( Node *graph[]) { Node *node0_0 = ( Node * )malloc( sizeof( Node ) ); Node *node0_1 = ( Node * )malloc( sizeof( Node ) ); Node *node0_2 = ( Node * )malloc( sizeof( Node ) ); Node *node1_1 = ( Node * )malloc( sizeof( Node ) ); Node *node1_0 = ( Node * )malloc( sizeof( Node ) ); Node *node1_3 = ( Node * )malloc( sizeof( Node ) ); Node *node1_4 = ( Node * )malloc( sizeof( Node ) ); Node *node2_2 = ( Node * )malloc( sizeof( Node ) ); Node *node2_0 = ( Node * )malloc( sizeof( Node ) ); Node *node2_5 = ( Node * )malloc( sizeof( Node ) ); Node *node2_6 = ( Node * )malloc( sizeof( Node ) ); Node *node3_3 = ( Node * )malloc( sizeof( Node ) ); Node *node3_1 = ( Node * )malloc( sizeof( Node ) ); Node *node3_7 = ( Node * )malloc( sizeof( Node ) ); Node *node4_4 = ( Node * )malloc( sizeof( Node ) ); Node *node4_1 = ( Node * )malloc( sizeof( Node ) ); Node *node4_7 = ( Node * )malloc( sizeof( Node ) ); Node *node5_5 = ( Node * )malloc( sizeof( Node ) ); Node *node5_2 = ( Node * )malloc( sizeof( Node ) ); Node *node5_7 = ( Node * )malloc( sizeof( Node ) ); Node *node6_6 = ( Node * )malloc( sizeof( Node ) ); Node *node6_2 = ( Node * )malloc( sizeof( Node ) ); Node *node6_7 = ( Node * )malloc( sizeof( Node ) ); Node *node7_7 = ( Node * )malloc( sizeof( Node ) ); Node *node7_3 = ( Node * )malloc( sizeof( Node ) ); Node *node7_4 = ( Node * )malloc( sizeof( Node ) ); Node *node7_5 = ( Node * )malloc( sizeof( Node ) ); Node *node7_6 = ( Node * )malloc( sizeof( Node ) ); node0_0->vertex = node1_0->vertex = node2_0->vertex = 0; node0_1->vertex = node1_1->vertex = node3_1->vertex = node4_1->vertex = 1; node0_2->vertex = node2_2->vertex = node5_2->vertex = node6_2->vertex = 2; node1_3->vertex = node3_3->vertex = node7_3->vertex = 3; node1_4->vertex = node4_4->vertex = node7_4->vertex = 4; node2_5->vertex = node5_5->vertex = node7_5->vertex = 5; node2_6->vertex = node6_6->vertex = node7_6->vertex = 6; node3_7->vertex = node4_7->vertex = node5_7->vertex = node6_7->vertex = node7_7->vertex = 7; node0_0->link = node0_1; node0_1->link = node0_2; node0_2->link = NULL; graph[ 0 ] = node0_0; node1_1->link = node1_0; node1_0->link = node1_3; node1_3->link = node1_4; node1_4->link = NULL; graph[ 1 ] = node1_1; node2_2->link = node2_0; node2_0->link = node2_5; node2_5->link = node2_6; node2_6->link = NULL; graph[ 2 ] = node2_2; node3_3->link = node3_1; node3_1->link = node3_7; node3_7->link = NULL; graph[ 3 ] = node3_3; node4_4->link = node4_1; node4_1->link = node4_7; node4_7->link = NULL; graph[ 4 ] = node4_4; node5_5->link = node5_2; node5_2->link = node5_7; node5_7->link = NULL; graph[ 5 ] = node5_5; node6_6->link = node6_2; node6_2->link = node6_7; node6_7->link = NULL; graph[ 6 ] = node6_6; node7_7->link = node7_3; node7_3->link = node7_4; node7_4->link = node7_5; node7_5->link = node7_6; node7_6->link = NULL; graph[ 7 ] = node7_7; } void dfs( int v, int *visited, Node *graph[] ) { Node *w = ( Node * )malloc( sizeof( Node ) ); visited[ v ] = 1; printf("%d->", v ); for ( w = graph[ v ]; w; w = w->link ){ if ( !visited[ w->vertex ] ){ dfs( w->vertex, visited, graph ); } } } int main( void ) { Node *graph[ MAX_VERTICES ]; int visited[ MAX_VERTICES ]; memset( graph, 0, sizeof( Node * ) * MAX_VERTICES ); memset( visited, 0, sizeof( int ) * MAX_VERTICES ); initNode( graph ); dfs( 0, visited, graph ); printf("NULL\n"); return 0; }
程序输出:
这种方法是我经常用的,但是没有free,是不好的设计.但是我确实不知道怎么去free(良好的free掉).然后我再想,在设计中更重要的是安全性,既然free很难,那我们不用malloc不就行了吗?于是我手动分配了一个确定的内存空间用来存储结点:
PS:这种方法是我个人比较推荐的(我也说不出为什么,总感觉malloc很危险就是了)
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VERTICES 50 typedef struct NODE{ int vertex; struct NODE *link; }Node; void initNode( Node *graph[], struct NODE stack[] ) { stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ]; stack[ 1 ].vertex = 1, stack[ 1 ].link = &stack[ 2 ]; stack[ 2 ].vertex = 2, stack[ 2 ].link = NULL; stack[ 3 ].vertex = 1, stack[ 3 ].link = &stack[ 4 ]; stack[ 4 ].vertex = 0, stack[ 4 ].link = &stack[ 5 ]; stack[ 5 ].vertex = 3, stack[ 5 ].link = &stack[ 6 ]; stack[ 6 ].vertex = 4, stack[ 6 ].link = NULL; stack[ 7 ].vertex = 2, stack[ 7 ].link = &stack[ 8 ]; stack[ 8 ].vertex = 0, stack[ 8 ].link = &stack[ 9 ]; stack[ 9 ].vertex = 5, stack[ 9 ].link = &stack[ 10 ]; stack[ 10 ].vertex = 6, stack[ 10 ].link = NULL; stack[ 11 ].vertex = 3, stack[ 11 ].link = &stack[ 12 ]; stack[ 12 ].vertex = 1, stack[ 12 ].link = &stack[ 13 ]; stack[ 13 ].vertex = 7, stack[ 13 ].link = NULL; stack[ 14 ].vertex = 4, stack[ 14 ].link = &stack[ 15 ]; stack[ 15 ].vertex = 1, stack[ 15 ].link = &stack[ 16 ]; stack[ 16 ].vertex = 7, stack[ 16 ].link = NULL; stack[ 17 ].vertex = 5, stack[ 17 ].link = &stack[ 18 ]; stack[ 18 ].vertex = 2, stack[ 18 ].link = &stack[ 19 ]; stack[ 19 ].vertex = 7, stack[ 19 ].link = NULL; stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ]; stack[ 21 ].vertex = 2, stack[ 21 ].link = &stack[ 22 ]; stack[ 22 ].vertex = 7, stack[ 22 ].link = NULL; stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ]; stack[ 24 ].vertex = 3, stack[ 24 ].link = &stack[ 25 ]; stack[ 25 ].vertex = 4, stack[ 25 ].link = &stack[ 26 ]; stack[ 26 ].vertex = 5, stack[ 26 ].link = &stack[ 27 ]; stack[ 27 ].vertex = 6, stack[ 27 ].link = NULL; graph[ 0 ] = &stack[ 0 ]; graph[ 1 ] = &stack[ 3 ]; graph[ 2 ] = &stack[ 7 ]; graph[ 3 ] = &stack[ 11 ]; graph[ 4 ] = &stack[ 14 ]; graph[ 5 ] = &stack[ 17 ]; graph[ 6 ] = &stack[ 20 ]; graph[ 7 ] = &stack[ 23 ]; } void dfs( int v, int *visited, Node *graph[] ) { Node *w = ( Node * )malloc( sizeof( Node ) ); visited[ v ] = 1; printf("%d->", v ); for ( w = graph[ v ]; w; w = w->link ){ if ( !visited[ w->vertex ] ){ dfs( w->vertex, visited, graph ); } } } int main( void ) { Node *graph[ MAX_VERTICES ]; int visited[ MAX_VERTICES ]; struct NODE stack[ MAX_VERTICES ]; memset( graph, 0, sizeof( Node * ) * MAX_VERTICES ); memset( visited, 0, sizeof( int ) * MAX_VERTICES ); memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES ); initNode( graph, stack ); dfs( 0, visited, graph ); printf("NULL\n"); return 0; }
程序输出:
2. 广度优先搜索
广度优先搜索类似于层次遍历,写写看:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VERTICES 50 typedef struct NODE{ int vertex; struct NODE *link; }Node; void initNode( Node *graph[], struct NODE stack[] ) { stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ]; stack[ 1 ].vertex = 1, stack[ 1 ].link = &stack[ 2 ]; stack[ 2 ].vertex = 2, stack[ 2 ].link = NULL; stack[ 3 ].vertex = 1, stack[ 3 ].link = &stack[ 4 ]; stack[ 4 ].vertex = 0, stack[ 4 ].link = &stack[ 5 ]; stack[ 5 ].vertex = 3, stack[ 5 ].link = &stack[ 6 ]; stack[ 6 ].vertex = 4, stack[ 6 ].link = NULL; stack[ 7 ].vertex = 2, stack[ 7 ].link = &stack[ 8 ]; stack[ 8 ].vertex = 0, stack[ 8 ].link = &stack[ 9 ]; stack[ 9 ].vertex = 5, stack[ 9 ].link = &stack[ 10 ]; stack[ 10 ].vertex = 6, stack[ 10 ].link = NULL; stack[ 11 ].vertex = 3, stack[ 11 ].link = &stack[ 12 ]; stack[ 12 ].vertex = 1, stack[ 12 ].link = &stack[ 13 ]; stack[ 13 ].vertex = 7, stack[ 13 ].link = NULL; stack[ 14 ].vertex = 4, stack[ 14 ].link = &stack[ 15 ]; stack[ 15 ].vertex = 1, stack[ 15 ].link = &stack[ 16 ]; stack[ 16 ].vertex = 7, stack[ 16 ].link = NULL; stack[ 17 ].vertex = 5, stack[ 17 ].link = &stack[ 18 ]; stack[ 18 ].vertex = 2, stack[ 18 ].link = &stack[ 19 ]; stack[ 19 ].vertex = 7, stack[ 19 ].link = NULL; stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ]; stack[ 21 ].vertex = 2, stack[ 21 ].link = &stack[ 22 ]; stack[ 22 ].vertex = 7, stack[ 22 ].link = NULL; stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ]; stack[ 24 ].vertex = 3, stack[ 24 ].link = &stack[ 25 ]; stack[ 25 ].vertex = 4, stack[ 25 ].link = &stack[ 26 ]; stack[ 26 ].vertex = 5, stack[ 26 ].link = &stack[ 27 ]; stack[ 27 ].vertex = 6, stack[ 27 ].link = NULL; graph[ 0 ] = &stack[ 0 ]; graph[ 1 ] = &stack[ 3 ]; graph[ 2 ] = &stack[ 7 ]; graph[ 3 ] = &stack[ 11 ]; graph[ 4 ] = &stack[ 14 ]; graph[ 5 ] = &stack[ 17 ]; graph[ 6 ] = &stack[ 20 ]; graph[ 7 ] = &stack[ 23 ]; } void bfs( int v, int *visited, Node *graph[] ) { Node *stack[ MAX_VERTICES ]; int top = 0; int rear = 0; Node *w = ( Node * )malloc( sizeof( Node ) ); visited[ v ] = 1; printf("%d->", v ); stack[ top++ ] = graph[ v ]; while ( top != rear ){ w = stack[ rear++ ]; for ( ; w; w = w->link ){ if ( !visited[ w->vertex ] ){ printf("%d->", w->vertex ); stack[ top++ ] = graph[ w->vertex ]; visited[ w->vertex ] = 1; } } } } int main( void ) { Node *graph[ MAX_VERTICES ]; int visited[ MAX_VERTICES ]; struct NODE stack[ MAX_VERTICES ]; memset( graph, 0, sizeof( Node * ) * MAX_VERTICES ); memset( visited, 0, sizeof( int ) * MAX_VERTICES ); memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES ); initNode( graph, stack ); bfs( 0, visited, graph ); printf("NULL\n"); return 0; }
程序输出:
3. 测试连通分支
就是测试上例中的visited是否有断开(值为0)的点.假设我们伪造两个不连接的图作为测试:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VERTICES 50 typedef struct NODE{ int vertex; struct NODE *link; }Node; void initNode( Node *graph[], struct NODE stack[] ) { stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ]; stack[ 1 ].vertex = 1, stack[ 1 ].link = &stack[ 2 ]; stack[ 2 ].vertex = 2, stack[ 2 ].link = NULL; stack[ 3 ].vertex = 1, stack[ 3 ].link = &stack[ 4 ]; stack[ 4 ].vertex = 0, stack[ 4 ].link = NULL; stack[ 7 ].vertex = 2, stack[ 7 ].link = &stack[ 8 ]; stack[ 8 ].vertex = 0, stack[ 8 ].link = NULL; stack[ 11 ].vertex = 3, stack[ 11 ].link = &stack[ 12 ]; stack[ 12 ].vertex = 7, stack[ 12 ].link = NULL; stack[ 14 ].vertex = 4, stack[ 14 ].link = &stack[ 15 ]; stack[ 15 ].vertex = 7, stack[ 15 ].link = NULL; stack[ 17 ].vertex = 5, stack[ 17 ].link = &stack[ 18 ]; stack[ 18 ].vertex = 7, stack[ 18 ].link = NULL; stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ]; stack[ 21 ].vertex = 7, stack[ 21 ].link = NULL; stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ]; stack[ 24 ].vertex = 3, stack[ 24 ].link = &stack[ 25 ]; stack[ 25 ].vertex = 4, stack[ 25 ].link = &stack[ 26 ]; stack[ 26 ].vertex = 5, stack[ 26 ].link = &stack[ 27 ]; stack[ 27 ].vertex = 6, stack[ 27 ].link = NULL; graph[ 0 ] = &stack[ 0 ]; graph[ 1 ] = &stack[ 3 ]; graph[ 2 ] = &stack[ 7 ]; graph[ 3 ] = &stack[ 11 ]; graph[ 4 ] = &stack[ 14 ]; graph[ 5 ] = &stack[ 17 ]; graph[ 6 ] = &stack[ 20 ]; graph[ 7 ] = &stack[ 23 ]; } void bfs( int v, int *visited, Node *graph[] ) { Node *stack[ MAX_VERTICES ]; int top = 0; int rear = 0; Node *w = ( Node * )malloc( sizeof( Node ) ); visited[ v ] = 1; printf("%d->", v ); stack[ top++ ] = graph[ v ]; while ( top != rear ){ w = stack[ rear++ ]; for ( ; w; w = w->link ){ if ( !visited[ w->vertex ] ){ printf("%d->", w->vertex ); stack[ top++ ] = graph[ w->vertex ]; visited[ w->vertex ] = 1; } } } } void connected( int *visited, int len, Node *graph[] ) { int i = 0; for ( i = 0; i < len; i++ ){ if ( !visited[ i ] ){ bfs( i, visited, graph ); printf("NULL\n"); } } } int main( void ) { Node *graph[ MAX_VERTICES ]; int visited[ MAX_VERTICES ]; struct NODE stack[ MAX_VERTICES ]; memset( graph, 0, sizeof( Node * ) * MAX_VERTICES ); memset( visited, 0, sizeof( int ) * MAX_VERTICES ); memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES ); initNode( graph, stack ); bfs( 0, visited, graph ); printf("NULL\n"); connected( visited, 8, graph ); return 0; }
程序输出:
PS:之所以不厌其烦的把所有的代码贴出来.是因为我刚开始学习程序的时候,很多的高手总是习惯把关键的代码贴出来,但是没有贴出全部,结果对我来说,怎么写也无法运行代码.这就是为什么我习惯贴出全部代码的原因.
4. 生成树
在深度优先搜索或者广度优先搜索中,打印出来的边构成的树,为图的生成树.
这在城市建设通讯线路的成本中有设计,当然,权值也在那里体现.
5. 双连通分支与关节点
关节点:图G中的一个顶点v,如果删除v以及关联在v上的所有边后,得到的新图至少包含两个连通分支.如下图:
关节点为1,3,5,7,如下图所示:
双连通图是没有关节点的连通图.连通无向图G的双连通分支是图G中的一个最大双连通子图H.
我们现在通过深度优先搜索树来描述如何找到最大双连通子图(描述不详细,具体参考<数据结构(C语言版)>).我们从结点3开始深度优先搜索,则如下图所示:
上图中的曲线(PPT中我不知道虚线怎么画)代表的是回退边.有两个结论:
当且仅当深度优先生成树的根顶点至少有两个儿子,它就是一个关节点.
任何非根顶点u是一个关节点,当且仅当u至少有一个儿子w,且从w出发,不能通过w的后代顶点和一条回退边到达u的任意一个祖先顶点.
这样,我们可以给每个顶点u定义low值,low(u)等于从u出发,经过一条由其后代顶点形成的路径和一条回退边,所能到达的具有最小深度优先编号顶点的编号(会死循环吗??)
因此,判断顶点u是否为关节点的方法是:如果顶点u是生成树的根节点,且u至少有两个儿子,则u是关节点;如果u不是根节点,那么当且仅当u有一个儿子w,使得low(w)>=dfn(u),则u是关节点.则下表可以显示上例中的dfn,low的关系:
顶点 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
dfn | 4 | 3 | 2 | 0 | 1 | 5 | 6 | 7 | 9 |
low | 4 | 3 | 0 | 0 | 0 | 5 | 5 | 7 | 9 |
为什么 | 列的长 | 度不能 | 超过 | 10 | ? | ? | ? | ? | ? |
这里的问题是:如何构建良好的数据结构来计算dfn和low的值.
我们来尝试写一下代码(有九天没写C语言了,瞬间感觉有点陌生.加油吧,为了梦想,和无怨无悔的人生).
这个程序难是难在它需要生成树.所以自学很麻烦的,因为你漏掉一点就会使程序完全跑不通.
先把不完整的代码贴出来吧,然后第六章的图和第十章的查找后面再来啃,要一步步来.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_VERTICES 50 #define MIN2(x,y) ((x) < (y) ? (x) : (y)) typedef struct NODE{ int vertex; struct NODE *link; }Node; void initNode( Node *graph[], struct NODE stack[] ) { stack[ 0 ].vertex = 0, stack[ 0 ].link = &stack[ 1 ]; stack[ 1 ].vertex = 1, stack[ 1 ].link = NULL; stack[ 2 ].vertex = 1, stack[ 2 ].link = &stack[ 3 ]; stack[ 3 ].vertex = 0, stack[ 3 ].link = &stack[ 4 ]; stack[ 4 ].vertex = 2, stack[ 4 ].link = &stack[ 5 ]; stack[ 5 ].vertex = 3, stack[ 5 ].link = NULL; stack[ 6 ].vertex = 2, stack[ 6 ].link = &stack[ 7 ]; stack[ 7 ].vertex = 1, stack[ 7 ].link = &stack[ 8 ]; stack[ 8 ].vertex = 4, stack[ 8 ].link = NULL; stack[ 9 ].vertex = 3, stack[ 9 ].link = &stack[ 10 ]; stack[ 10 ].vertex = 1, stack[ 10 ].link = &stack[ 11 ]; stack[ 11 ].vertex = 4, stack[ 11 ].link = &stack[ 12 ]; stack[ 12 ].vertex = 5, stack[ 12 ].link = NULL; stack[ 13 ].vertex = 4, stack[ 13 ].link = &stack[ 14 ]; stack[ 14 ].vertex = 2, stack[ 14 ].link = &stack[ 15 ]; stack[ 15 ].vertex = 3, stack[ 15 ].link = NULL; stack[ 16 ].vertex = 5, stack[ 16 ].link = &stack[ 17 ]; stack[ 17 ].vertex = 3, stack[ 17 ].link = &stack[ 18 ]; stack[ 18 ].vertex = 7, stack[ 18 ].link = &stack[ 19 ]; stack[ 19 ].vertex = 8, stack[ 19 ].link = NULL; stack[ 20 ].vertex = 6, stack[ 20 ].link = &stack[ 21 ]; stack[ 21 ].vertex = 5, stack[ 21 ].link = &stack[ 22 ]; stack[ 22 ].vertex = 7, stack[ 22 ].link = NULL; stack[ 23 ].vertex = 7, stack[ 23 ].link = &stack[ 24 ]; stack[ 24 ].vertex = 5, stack[ 24 ].link = &stack[ 25 ]; stack[ 25 ].vertex = 6, stack[ 25 ].link = &stack[ 26 ]; stack[ 26 ].vertex = 8, stack[ 26 ].link = &stack[ 27 ]; stack[ 27 ].vertex = 9, stack[ 27 ].link = NULL; stack[ 28 ].vertex = 8, stack[ 28 ].link = &stack[ 29 ]; stack[ 29 ].vertex = 7, stack[ 29 ].link = &stack[ 30 ]; stack[ 30 ].vertex = 9, stack[ 30 ].link = NULL; stack[ 31 ].vertex = 9, stack[ 31 ].link = &stack[ 32 ]; stack[ 32 ].vertex = 7, stack[ 32 ].link = &stack[ 33 ]; stack[ 33 ].vertex = 8, stack[ 33 ].link = NULL; graph[ 0 ] = &stack[ 0 ]; graph[ 1 ] = &stack[ 2 ]; graph[ 2 ] = &stack[ 6 ]; graph[ 3 ] = &stack[ 9 ]; graph[ 4 ] = &stack[ 13 ]; graph[ 5 ] = &stack[ 16 ]; graph[ 6 ] = &stack[ 20 ]; graph[ 7 ] = &stack[ 23 ]; graph[ 8 ] = &stack[ 28 ]; graph[ 9 ] = &stack[ 31 ]; } void dfnlow( int u, int v, Node *graph[], int *dfn, int *low, int *num ) { Node *ptr = ( Node * )malloc( sizeof( Node ) ); int w; dfn[ u ] = low[ u ] = ( *num )++; //注意,++的优先级比*高,所以要加括号 for ( ptr = graph[ u ]; ptr; ptr = ptr->link ){ w = ptr->vertex; if ( dfn[ w ] < 0 ){ dfnlow( w, u, graph, dfn, low, num ); low[ u ] = MIN2( low[ u ], low[ w ] ); } else if ( w != v ){ low[ u ] = MIN2( low[ u ], dfn[ w ] ); } } } int main( void ) { Node *graph[ MAX_VERTICES ]; int visited[ MAX_VERTICES ]; struct NODE stack[ MAX_VERTICES ]; int dfn[ MAX_VERTICES ]; int low[ MAX_VERTICES ]; int num = 0; int i = 0; memset( graph, 0, sizeof( Node * ) * MAX_VERTICES ); memset( visited, 0, sizeof( int ) * MAX_VERTICES ); memset( stack, 0, sizeof( struct NODE ) * MAX_VERTICES ); memset( dfn, -1, sizeof( int ) * MAX_VERTICES ); memset( low, -1, sizeof( int ) * MAX_VERTICES ); initNode( graph, stack ); dfnlow( 3, -1, graph, dfn, low, &num ); for ( i = 0; dfn[ i ] != -1; i++ ){ printf("%d ", dfn[ i ] ); } printf("\n"); for ( i = 0; low[ i ] != -1; i++ ){ printf("%d ", low[ i ] ); } printf("\n"); return 0; }