利用深度优先搜索算法寻找割点

摘要:利用深度优先搜索去寻找割点.

(1)定义:什么叫做割点?割点的定义是针对无向连通图的.如果删除某一个节点后该图仍然是连通的,那么这个图是双连通的.否则被删除的节点叫做割点.

(2)寻找割点的基本思路:

[1]首先利用深度优先搜索给图进行编号.对每一个节点我们称它的编号为先序编号Num[v]。然后对深度搜索优先树每一个定点v计算它能够通过一条背向边或者树的零边或其他边达到的先序编号最低的顶点,称为Low[v];

[2]背向边的定义是:在深度优先搜索时对节点v的邻接节点访问,发现某个节点w已经被访问了,那么就有一条背向边(v,w).

[3]判定割点的定理与其证明:

{1}根是割点当前仅当它有多余一个的儿子(在优先生成树中),因为一个儿子不可能不通过根到达另一个儿子。试想:假设可能,那么它们之间就存在一条背向边,或者根的某个子孙通过背向边连接到根的另一棵子树.根据深度优先搜索的算法,只有根的某个子树上所有可能的点都被访问完,才会进入下棵子树(另一个儿子的儿子之间不会有背向边.
{2}如果非根节点,那么当且仅当它有某个儿子w使得Low[w] Num[v]。现在证明这个结论:如果Low[w] Num[v],它的所有的子孙节点没有背向边能连接到它的祖先.因为如果有,那么它可以连接到它的某个祖先,这样的它的Low[w]将小于Num[v].很显然,在一个无向图中,如果这个节点被删除,那么它的子孙就不能访问到它的祖先了(因为唯一条路径树边被删除了).
{3}当然,我们要找出所有割点,那么还要证明如果一个节点v是割点,那么它一定满足Low[w] Num[v].我们采取反证法:如果一个割点v的所有儿子w都满足Low[w] < Num[v],那么w就可以通过背向边连接到v的祖先.如果v的消失使得节点x不能被访问,如果x是v的儿子,那么除了它的儿子的所有节点会通过连接到它的某个祖先然后通过连接到某个儿子w的背向边进入它的子树从而连接到x,而它的儿子本身就可以不通过v连接到x.如果x不是v的儿子,那么除了它和它的儿子,其余节点本来就可以不通过v连接到x(图本身连通),而v的儿子则可以通过背向边绕过v从而到达其他节点,再从其他节点连接到x.

(4)

#include "stdafx.h"
#include "图论ADT.h"
int static Counter = 0;
int static Rootsize = 0;
bool static Isvisited[Number] = {false}; 
int static Num[Number] = {-1};
int static Parent[Number] = {-1};
int static Low[Number] = {-1};
void FindArt(Graph G,int StartVertex)
{
    int v = StartVertex,w;
    Isvisited[v] = true;
    Num[v] = Counter++;//给v编号
    Low[v] = Num[v];
    G[v] = G[v]->Next;
    while(G[v]!=NULL)//遍历v的所有adjancent vertex
    {
        w = G[v]->Element;
        if(!Isvisited[w])
        {
            Parent[w] = v;
            if(Parent[v]== -1 )
                Rootsize++;
                FindArt(G,w);//此处访问完所有节点
                if (Low[w]>=Num[v])//代表(不通过v)只能访问v以下的节点-必须通过v才能访问v以上节点
                {
                    if (Parent[v] != -1)
                {
                    printf("%d is the articulation point\n",v);
                }
                    else if (Rootsize>=2)//判断是根的情况
                    {
                        printf("%d is the articulation point\n",v);
                    }
                }
                    Low[v] = Low[v]<Low[w]?Low[v]:Low[w];
        }
         else if (Parent[v] != w)//不是父子关系
            {
                Low[v] = Low[v]<Num[w]?Low[v]:Num[w];
            }
        G[v] = G[v]->Next;
    }
}
void FindArt_drive(Graph G,int startvertex)
{
 Counter = 0;
 Rootsize = 0;
 for (int i = 0;i<=Number-1;i++)
 {
 Isvisited[i] = false; 
 Num[i] = -1;
 Parent[i] = -1;
 Low[i] = -1;
 }
 FindArt(G,startvertex);
}

你可能感兴趣的:(利用深度优先搜索算法寻找割点)