//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
今日推荐
周排行