求关节点

//low(v) = Min{visited[v] , low(w) ,visited[k]}
//visited[v] -> 深度优先 该点访问次序
//low(w) ->  子树 的low 值
//visited[k] -> 回边的 次序
// 条件 low[w] >= visited[v]
#include <iostream>
#include <vector>
using namespace std;
#define NODEMAXSIZE 128

//邻接表
struct BaseNode
{
    BaseNode(){
        m_tailIndex = -1;
        m_Next = NULL;
        m_weight = -1;
    }
    ~BaseNode()
    {
        while (m_Next)
        {
            BaseNode * t = m_Next;
            m_Next = m_Next->m_Next;
            delete t;
            t = NULL;
        }
    }
    int m_tailIndex;        //弧尾
    BaseNode * m_Next;
    int m_weight;           //权值
};

struct GraphNode
{
    GraphNode()
    {
        m_headIndex = -1;
        m_firstNode = NULL;
    }

    int m_headIndex;        //弧头
    BaseNode *m_firstNode;
};

class Graph
{
public:
    bool  CreateGraph();
    void  DFS(int index,int& second);
public:
    GraphNode m_Node[ NODEMAXSIZE ];

    int m_nVertSize;    //顶点个数

    int m_nEdgeSize;    //边个数
};

bool  Graph::CreateGraph()
{
    cin >> m_nVertSize;

    for (int i = 1; i <= m_nVertSize; i++)
    {
        m_Node[i].m_headIndex = i;
    }
    cin >> m_nEdgeSize;
    for (int i = 0; i < m_nEdgeSize; i++)
    {
        int nHead, nTail;
        cin >> nHead >> nTail;
        if (m_Node[nHead].m_firstNode == NULL)
        {
            m_Node[nHead].m_firstNode = new BaseNode;
            m_Node[nHead].m_firstNode->m_tailIndex = nTail;
            m_Node[nHead].m_firstNode->m_weight = 1;
        }
        else
        {
            BaseNode * t = m_Node[nHead].m_firstNode;
            while (t->m_Next != NULL)
            {
                t = t->m_Next;
            }
            t->m_Next = new BaseNode;
            t->m_Next->m_tailIndex = nTail;
            t->m_Next->m_weight = 1;
        }

        if (m_Node[nTail].m_firstNode == NULL)
        {
            m_Node[nTail].m_firstNode = new BaseNode;
            m_Node[nTail].m_firstNode->m_tailIndex = nHead;
            m_Node[nTail].m_firstNode->m_weight = 1;
        }
        else
        {
            BaseNode * t = m_Node[nTail].m_firstNode;
            while (t->m_Next != NULL)
            {
                t = t->m_Next;
            }
            t->m_Next = new BaseNode;
            t->m_Next->m_tailIndex = nHead;
            t->m_Next->m_weight = 1;
        }



    }
    return true;
}

int low[NODEMAXSIZE], visited[NODEMAXSIZE];
vector<int> guanJieDian;
void   Graph::DFS(int index, int& second)
{
    cout << "访问" << index<<endl;
    int min = ++second;
    visited[index] = second;

    BaseNode * t = m_Node[index].m_firstNode;
    for (; t != NULL; t = t->m_Next)
    {
        //没有访问过 是它的子节点
        if (visited[t->m_tailIndex] == 0)
        {
            DFS(t->m_tailIndex, second );

            if (low[t->m_tailIndex] < min)
            {
                min = low[t->m_tailIndex];
            }
            if ( low[t->m_tailIndex] >= visited[index])
            {
                //cout << "关节点 = "<<index << endl; 
                if (find(guanJieDian.begin(), guanJieDian.end(), index) == guanJieDian.end())
                {
                    guanJieDian.push_back(index);
                }
            }
        }
        else if (  visited[t->m_tailIndex] < min){
            //是它的回边
            min = visited[t->m_tailIndex];
        }
    }
    low[index] = min;
    cout << "low" << index << "=" << min << endl;
}


void FindArticul(Graph g){

    memset(low, 1, sizeof(low));
    memset(visited, 0, sizeof(visited));
    int nCount = 1;
    guanJieDian.clear();
    //标记根节点已访问
    visited[1] = 1;
    //从根节点的邻接点访问
    BaseNode *t = g.m_Node[1].m_firstNode;
    if (t == NULL)
    {
        cout << "MMP" << endl;
        return;
    }
    int nStart = t->m_tailIndex;
    g.DFS(nStart, nCount);

    //只有一条子树 没有分支  根节点不是关节点
    if (nCount < g.m_nVertSize)
    {
        if (find(guanJieDian.begin(), guanJieDian.end(), 1) == guanJieDian.end())
        {
            guanJieDian.push_back(1);
        }
        //从根节点的下一个邻接点遍历
        t = t->m_Next;
        while (t)
        {
            nStart = t->m_tailIndex;
            g.DFS(nStart, nCount);
            t = t->m_Next;
        }
    }


    cout << "关节点个数为" << guanJieDian.size() << endl;
    vector<int>::iterator it = guanJieDian.begin();
    for (; it != guanJieDian.end(); it++)
    {
        cout << " " << (*it) << " ";
    }
    guanJieDian.clear();
}
int main()
{
    while (true)
    {
        Graph g;
        if (g.CreateGraph())
        {
            FindArticul(g);
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/seanbill/article/details/80155663