-
关节点
若删去顶点v
以及和 v 相关联的各边
之后,将图的一个连通分量
分割成两个或者两个以上的连通分量
,则称顶点 v 为该图的一个关节点
。 -
重连通图
一个没有关节点的连通图称为重连通图
。 -
重连通图的性质
任意一对顶点之间至少存在两条路径,则在删去某个顶点
以及依附于该顶点的各边
时也不破坏图的连通性。
连通度:若在连通图上至少删去 k 个顶点 才能破坏图的连通性,则称此图的连通度
为 k。 -
关节点
和重连通
在实际中应用较多,
如一个表示通信网络的图的连通度很高,其系统可靠,无论是哪一站点出现故障或者遭到外界破坏,都不会影响系统的正常工作。 -
如下图,是连通图,但不是重连通图
图中有 4 个关节点 A、B、D 和 G。
若删去顶点 B 以及所有依附于 B 的边,G5 就会被分割成 3 个连通分量:
{ A , C , F , L , M , J }
{ G , H , I , K }
{ D , E }
因此 关节点 也叫作 割点。
利用深度优先搜索来求关节点,判断是否是重连通图
图 7.20 所示为从顶点 A 出发深度优先搜索遍历 图 G~5~
所得的 深度优先生成树
,图中 实线
表示 树边
,虚线
表示 回边
(即在图中但 不在 生成树上的边)。
对树中任一顶点 v 而言,其 孩子结点
为在它之后搜索到的邻接点,而其 双亲结点
和 由回边联结的祖先结点
是在它之前搜索到的邻接点。
1、若生成树的根有两棵或两棵以上的子树,则此根必为关节点。因为图中不存在联结不同子树中顶点的边
,因此若删去 根顶点
,生成树
便变成 生成森林
,如上图 7.20 中的 顶点 A
。
2、若生成树中某个 非叶子顶点v
,其 某一棵子树的根 和 该子树中的其他结点 均没有指向 v 的祖先的回边,则 v 为关节点。 因为若删去 v,则其子树和图的其他部分被分割开来,如上图 7.20 中的顶点 B、D 和 G。
判断给叶子结点是否是关节点的算法
-
引入一个
新的函数
low,由依次深度优先搜索遍历
便可求得连通图中存在的所有关节点。
定义 visited[v] 为深度优先搜索遍历连通图时访问顶点 v 的次序号
如下
v 是 待判断的结点的标号、在图中的位置。
w 是 顶点 v 在深度优先生成树上的孩子结点。
k 是 顶点 v 在深度优先生成树上由回边连接的祖先结点。 -
判断依据
若对于某个顶点 v,存在孩子结点 w 且 low [ w ] >= visited [ v ],则该顶点必为关节点。
因为当w是v的孩子结点时 low[w] >= visited[v] ,表明 w 及其子孙均无指向 v 的祖先的回边,由此 v 是关节点。
判断某个非叶子顶点是否是关节点
- 连通图G 以
邻接表
作为存储结构
#define MAX_VERTEX_NUM 20
typedef struct ArcNode
{
int adjvex; // 该弧所指向的顶点的位置
struct ArcNode *nextarc; // 指向的下一条弧的指针
InfoType *info; // 指向该弧相关信息的指针
} ArcNode; // 表中结点,表示一条弧(也可以是一条边)
typedef struct VNode
{
VertexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附于该顶点的弧的指针
} VNode, AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices; //存放顶点结点的顺序表
int vexnum, arcnum; //图的当前顶点数和弧数
int kind; //图的种类,标志
} ALGraph;
void FindArticul(ALGraph G)
{
count = 1;
visited[0] = 1;
for(i=1; i<G.vexnum; i++)
{
visited[i] = 0;
}
p = G.vertices[0].firstarc;
v = p->adjvex;
DFSArticul(G, v);
if(count < G.vexnum)
{
printf(0, G.vertices[0].data);
while(p->nextarc)
{
p = p->nextarc;
v = p->adjvex;
if(visited[v] == 0)
{
DFSArticul(g, v);
}
}
}
}
void DFSArticul(ALGraph G, int v0)
{
visited[v0] = min = ++count;
for(p=G.vertices[v0].firstarc;
p;
p=p->nextarc;)
{
w = p->adjvex; // w 是 v0 的邻接顶点
if(visited[w] == 0) // w 未被访问,是 v0 的孩子
{
DFSArticul(G, w); // 返回之前求得 low[w]
if(low[w] < min)
{
min = low[w];
}
if(low[w] >= visited[v0]) // 此为关节点
{
printf(v0, G.vertices[v0].data);
}
}
else if(visited[w] < min)
{
min = visited[w];
}
}
low[v0] = min; // 返回前求得 v0 的值
}
- 图 G5 中各顶点计算所得 visited 和 low 的函数值