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;
}