总结一下关节点算法:
主要分为三部分:
1.叶子节点一定不是关节点
2.根节点是一个关节点当他有多个孩子节点时
3.中间节点时一个关节点当它的子树没有回边到它的祖先节点
见代码。
邻接表表示法建树
struct Node{ //边表节点
int adjvex; //改弧所指向的顶点的位置
Node *next; //指向下一条弧的指针
};
struct Vnode{ //顶点表节点
int vertex; //顶点标志
Node* firstEdge; //顶点第一条弧的指针
};
struct Graph{
struct Vnode* adjList; //邻接表数组
int vNum; //点的总数
int eNum; //边的总数
};
建立树:
void createGraph(Graph* G){
int V_NUM = 4010;
//int v_num = 0;
//int e_num = 0;
int v_index = 0;
Node* s;
//cout<<"请输入顶点数:";
//cin>>v_num;
//cout<<"请输入边数:";
//cin>>e_num;
//G->eNum = V_NUM;
G->vNum = V_NUM;
//cout<<"请输入顶点编号(从0开始):"<<endl;
cout<<"顶点编号为(从0开始):"<<endl;
G->adjList = new Vnode[V_NUM];
for(int i=0; i < G->vNum; i++){
//cin>>v_index;
cout<<i<<" ";
G->adjList[i].vertex = i;//v_index;
G->adjList[i].firstEdge = NULL;
}
cout<<endl;
cout<<"请输入由两个顶点构成的边,实例: 0 1"<<endl;
ifstream in("data\\data3.txt");
if(! in.is_open()){
cout<<"Error opening file";
exit(1);
}
int index1, index2;
char* s1;
int count = 0;
//for(int j=0; j < G->eNum; j++){
while(in>>index1>>index2>>s1){
count ++;
//cin>>index1;
//cin>>index2;
s = new Node();
s->adjvex = index2;
s->next = NULL;
//无向图,插入边
Node* p = G->adjList[index1].firstEdge;
if( p == NULL){
G->adjList[index1].firstEdge = s;
}else{
while(p ->next != NULL){
p = p ->next;
}
p->next = s;
}
s = new Node();
s->adjvex = index1;
s->next = NULL;
Node* q = G->adjList[index2].firstEdge;
if(q == NULL){
G->adjList[index2].firstEdge = s;
}else{
while(q ->next != NULL){
q = q ->next;
}
q->next = s;
}
}
G->eNum = count;
//}
}
关节点代码:
void artPoint(Graph* G, int u, int *color, int *low, int *d, int *pred){
color[u] = 1; //表示已访问
low[u] = d[u] = ++ cnt;
for(Node * p = G->adjList[u].firstEdge; p != NULL; p = p ->next){
int v = p ->adjvex;
if(color[v] == 0){ //(u,v)是树边,v未被访问
pred[v] = u;
artPoint(G, v, color, low, d, pred); //访问v
low[u] = min(low[u], low[v]);
if(pred[u] == -1){ //u是根节点
//判断u是否还有第二个子节点
Node* q = p;
while(q->next != NULL){
if(color[q->next->adjvex] == 0){ //未访问
//判断关节点是否已存在
bool isExists = false;
for(int k=0; k < artPoints.size(); k++){
if(artPoints[k].vertex == G->adjList[u].vertex){
isExists = true;
}
}
if(!isExists){
artPoints.push_back(G->adjList[u]);
}
}
q = q -> next;
}
}else if(low[v] >= d[u]){
//判断关节点是否已存在
bool isExists = false;
for(int k=0; k < artPoints.size(); k++){
if(artPoints[k].vertex == G->adjList[u].vertex){
isExists = true;
}
}
if(!isExists){
//添加u到articulation points中
artPoints.push_back(G->adjList[u]);
}
}
}else if(v !=pred[u]){ //(u,v)是回边
low[u] = min(low[u], d[v]);
}
}
color[u] = 2; //表示访问结束
}