深度优先搜索寻找割点

如果无向连通图不存在删除后剩下的图不再连通的顶点,则该图为双连通。如果不是双连通的图,那么那些删除后剩下的图不再连通的顶点叫做割点。
执行深度优先搜索,按照搜索顺序给顶点编号Num。然后后序遍历,计算顶点的Low值,其为顶点通过该序(可能包含背向边)能到达的最小顶点。
Low(v)为各项中的最小值:
1、Num(v)
2、所有背向边(v,w)中的最低Num(w)
3、所有边(v,w)中的最低Low(w)
根是割点当且仅当他有多于一个的儿子。其他顶点则为v有某个儿子Low(w)>=Num(v)。


深度优先搜索寻找割点_第1张图片

深度优先搜索生成树

深度优先搜索寻找割点_第2张图片

头文件

#include 
#include 
using namespace std;

class Graph
{
public:
    explicit Graph(int vertexNum):v(vertexNum+1)
    {
        for(auto x:v)
        {
            x.parent=nullptr;
            x.adjacentList=vector{};
            x.visited=false;
            x.num=0;
            x.low=0;
        }


    }


    void setVertex(int vertexIndex,const vector<int> & adjacentIndex)
    {
        //创建邻接表
        for(auto i:adjacentIndex)
        {
            v[vertexIndex].adjacentList.push_back(&v[i]);
        }
    }

    void assignNum(int vertexIndex)
    {
        int sonNum=0;
        root=vertexIndex;
        assignNum(&v[vertexIndex]);
        assignLow(&v[vertexIndex]);
        for(auto itr=v.begin()+1;itr!=v.end();++itr)
        {
            if(itr->parent==&v[root])
                ++sonNum;

        }
        if(sonNum>=2)
            cout<<"V"<" is an articulation point"<void findArt(int vertexIndex)
    {
        findArt(&v[vertexIndex]);
        int sonNum=0;
        root=vertexIndex;

        for(auto itr=v.begin()+1;itr!=v.end();++itr)
        {
            if(itr->parent==&v[root])
                ++sonNum;

        }
        if(sonNum>=2)
            cout<<"V"<" is an articulation point"<void printNum()
    {
        for(int i=1;icout<" "<cout<private:
    struct Vertex
    {
        vector adjacentList;          //邻接表(邻接顶点以及之间的权重)
        Vertex*         parent;               //上一个节点
        bool            visited;             //顶点是否已经访问
        int             num;                 //先序编号
        int             low;                 //最低顶点编号

        explicit Vertex(const vector & adList=vector{})
        {

            parent=nullptr;
            adjacentList=adList;
            visited=false;
            num=0;
            low=0;
        }
    };

    std::vector v;
    int root;

    void assignNum(Vertex* ver);

    void assignLow(Vertex* ver);

    void findArt(Vertex * ver);
};

cpp文件

#include "Graph.hpp"



void Graph::assignNum(Vertex* ver)
{
    static int count=1;
    ver->visited=true;
    ver->num=count++;
    for(auto w:ver->adjacentList)
    {
        if(!w->visited)
        {
            w->parent=ver;
            assignNum(w);

        }
    }

}

void Graph::assignLow(Vertex* ver)
{

    ver->low=ver->num;
    for(auto  w:ver->adjacentList)
    {
        if(w->num>ver->num)
        {
            assignLow(w);
            if(w->low>=ver->num&&ver->num!=1)
                cout<<"V"<0]<<" is an articulation point"<if(ver->low>w->low)
                ver->low=w->low;
        }
        else
            if(w!=ver->parent)
                if(ver->low>w->num)
                    ver->low=w->num;

    }

}

//为先序编号和最小顶点编号两部分的组合
void Graph::findArt(Vertex* ver)
{
    static int count=1;
    ver->visited=true;
    ver->low=ver->num=count++;  //先序编号和最小顶点编号法则一

    for(auto  w:ver->adjacentList)
    {
        if(!w->visited)         //前向边
        {
            w->parent=ver;
            findArt(w);
            if(w->low>=ver->num&&ver->num!=1)
                cout<<"V"<0]<<" is an articulation point"<if(ver->low>w->low)
                ver->low=w->low;        //法则三
        }
        else
            if(w!=ver->parent)          //背向边,法则二,排除父节点
                if(ver->low>w->num)
                    ver->low=w->num;

    }


}

main.cpp

#include "Graph.hpp"
#include 
using namespace std;
int main(int argc, const char * argv[]) {
    //图由顶点和边组成
    Graph g(7);//顶点数

    //输入各个顶点的边(邻接顶点)
    g.setVertex(1, vector<int>{2,4});
    g.setVertex(2, vector<int>{1,3});
    g.setVertex(3, vector<int>{2,4,7});
    g.setVertex(4, vector<int>{1,3,5,6});
    g.setVertex(5, vector<int>{{4,6}});
    g.setVertex(6, vector<int>{4,5});
    g.setVertex(7, vector<int>{3});

    //g.assignNum(1);

    g.findArt(1);

    g.printNum();

    cout<return 0;
}

结果

V4 is an articulation point
V3 is an articulation point
1 1
2 1
3 1
4 1
5 4
6 4
7 7

你可能感兴趣的:(数据结构与算法)