//无向图:假若在删去顶点v以及和v相关联的各边之后,将图的一个连通分量分割成两个或两个以上的连通分量,则称顶点v为改图的一个关节点。一个没有关结点的连通图是重连通图。
//若在连通图上至少删去K个顶点才能破坏图的连通性,则称此刻的连通度为k.一个网络的连通度越高,其系统越安全可靠。
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
#include < limits.h >#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2typedef int Status ;
//-------------------------图的邻接表存储表示-------------------------------//(无向图)
#define MAX_VERTEX_NUM 20 //最大顶点个数(vertex顶点)
#define MAX_NAME 5 //关于顶点信息的字符串长度typedef int VRType ; //此处考虑无权图
typedef int InfoType ; //如果为字符信息,则可以用char;如果为权值,则可以用int.
typedef char VertexType[ MAX_NAME ]; //VertexType可以根据实际情况灵活设定类型!int,float,char…typedef struct ArcNode { //表结点
int adjvex ; //该弧所指向的顶点的位置
struct ArcNode *nextarc ; //指向下一条弧的指针
} ArcNode ;typedef struct VNode { //表头结点
VertexType data ; //顶点信息
ArcNode *firstarc ; //指向第一条依附该顶点的弧的指针
} VNode , AdjList[ MAX_VERTEX_NUM ] ;typedef struct {
AdjList vertices ;
int vexnum , arcnum ; //图当前的顶点树和弧数
} ALGraph ;
Status InitGraph( ALGraph *G ) ;
Status LocateVex( ALGraph G , VertexType u ) ;
Status CreateGraph( ALGraph *G ) ;
Status DestroyGraph( ALGraph *G ) ;//----------------------------------------------------------------//
int count ;
int low[ MAX_VERTEX_NUM ] ;
int visited[ MAX_VERTEX_NUM ] ;void FindArticul( ALGraph G ) ;
void DFSArticul( ALGraph G , int v0 ) ;
#include "head.h"
//--------------------------------------------------------------//
Status InitGraph( ALGraph *G )
{
int i ;printf( "Please input the number of vex and arc:" ) ;
scanf( "%d%d" , &( *G ).vexnum , &( *G ).arcnum ) ;printf("Input the vector of %d vex( %d char ): \n" , ( *G ).vexnum , MAX_NAME ) ;
for( i = 0 ; i < ( *G ).vexnum ; ++ i ) //构造顶点向量,同时也初始化表头结点数组。
{
scanf( "%s" , ( *G ).vertices[ i ].data ) ;
( *G ).vertices[ i ].firstarc = NULL ;
}return OK ;
}Status LocateVex( ALGraph G , VertexType u )
{
int k ;for( k = 0 ; k < G.vexnum ; ++ k )
{
if( strcmp( u , G.vertices[ k ].data ) == 0 )
return k ;
}
return EOF ;
}Status CreateGraph( ALGraph *G ) //构造无向图
{
int i ;
int l , j ; //定位弧头弧尾
VertexType va , vb ;
ArcNode *p ;InitGraph( G ) ;
printf( "Please input the vexa and vexb:\n" ) ;//-----------------------------------------------------//UDG
for( i = 0 ; i < ( *G ).arcnum ; ++ i )
{
scanf( "%s%s" , va , vb ) ;l = LocateVex( *G , va ) ; //弧尾 va----->vb
j = LocateVex( *G , vb ) ; //弧头p = ( ArcNode * )malloc( sizeof( ArcNode ) ) ; //adjvex
p->adjvex = j ; //Take care!
p->nextarc = ( *G ).vertices[ l ].firstarc ; //nextarc
( *G ).vertices[ l ].firstarc = p ;
p = ( ArcNode * )malloc( sizeof( ArcNode ) ) ;
p->adjvex = l ;
p->nextarc = ( *G ).vertices[ j ].firstarc ;
( *G ).vertices[ j ].firstarc = p ;
}
//---------------------------------------------------------------//
return OK ;
}Status DestroyGraph( ALGraph *G ) //释放资源和初始化
{
int i ;
ArcNode * p , * q ;
( *G ).arcnum = 0 ;
( *G ).vexnum = 0 ;for( i = 0 ; i < ( *G ).vexnum ; ++ i )
{
p = ( *G ).vertices[ i ].firstarc ;
while( p )
{
q = p->nextarc ;
free( p ) ;
p = q ;
}
}
return OK ;
}//-----------------------------------------------------------------------//
//关于这两个函数的知识与逻辑还要再思量!尤其是弄懂书本上的描叙。void FindArticul( ALGraph G ) //查找并输出G上全部关节点。全局量count对访问计数
{
int i , v ;
ArcNode *p ;count = 1 ;
low[ 0 ] = visited[ 0 ] = 1 ; //设定邻接表上0号顶点为生成树的根for( i = 1 ; i < G.vexnum ; ++ i ) //Take care about i =1 .
visited[ i ] = 0 ; //其余顶点尚未访问p = G.vertices[ 0 ].firstarc ;
v = p->adjvex ;DFSArticul( G , v ) ; //从第v顶点出发深度优先查找关节点
if( count < G.vexnum ) //生成树的根至少有两颗子树
{
printf( "第0号顶点------%s\n" , G.vertices[ 0 ].data ) ; //根是关节点,输出
while( p->nextarc )
{
p = p->nextarc ;
v = p->adjvex ;
if( visited[ 0 ] == 0 )
DFSArticul( G , v ) ;
}
}
}void DFSArticul( ALGraph G , int v0 ) //从第v0个顶点出发深度优先遍历图G,查找并输出关节点
{
int min , w ;
ArcNode *p ;visited[ v0 ] = min = ++ count ; //v0是第count个访问的顶点
for( p = G.vertices[ v0 ].firstarc ; p ; p = p->nextarc )//对V0的每个邻接点检查
{
w = p->adjvex ;
if( visited[ w ] == 0 )
{
DFSArticul( G , w ) ; //返回前求得low[ w ].
if( low[ w ] < min )
min = low[ w ] ;
if( low[ w ] >= visited[ v0 ] )
printf( "第%d个关节点------%s\n" , v0 , G.vertices[ v0 ].data ) ;
}
else
{
if( visited[ w ] < min )
min = visited[ w ] ;
}
} // for
low[ v0 ] = min ;
}//查找关节点!此处只针对无向图!如果想查找其他对象的关节点,则需做相印的改动!
int main( )
{
ALGraph G ;
int i ;CreateGraph( &G ) ;
printf( "Please output the articulation point: \n" ) ;
FindArticul( G ) ;printf( " i -- G.vertices[ i ].data -- visited[ i ] -- low[ i ]\n" ) ;
for( i = 0 ; i < G.vexnum ; ++ i )
printf( "%3d %12s %18d %14d\n" , i , G.vertices[ i ].data , visited[ i ] , low[ i ] ) ;return 0 ;
}
第七章(7).关结点和重连通分量
最新推荐文章于 2022-05-08 20:33:35 发布