第七章(7).关结点和重连通分量

//无向图:假若在删去顶点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 -2     

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值