打印图的2-连通分支
(注:部分定义、图像参考中科院陈玉福《计算机算法设计与分析》讲义)
2-连通图的定义:
如果无向连通图G中的任两个顶点都有两条不相交的路径相连通,连通图G称为2-连通的。
割点的定义:
无向连通图G中的顶点v称为割点,如果在G中去掉v及其关联的边,剩下的图就不再连通。如下图中,F、C、G为割点。
2-连通分支的定义:
由割点分割出来的图,如上图的2-连通分支如下5个:
为求得割点,以下定义最低深索数:
Low(u)=min{DFN(u),min{DFN(x)|(u,x)是回边},min{Low(w)|w是u的孩子}}
对于最低深索数的理解可参照下图:
红色数字标记每个顶点的最低深索数,黑色数字表示深度优先搜索时的搜索顺序Order。
如果定义“势”的概念,对某个2-连通分支T所包含的顶点v,“势”的值如下取到:
可以看到对于任意的顶点v属于T,所有顶点的”势”相同。
不同的2-连通分支”势”的大小按深度优先搜索的顺序决定,先搜索到的2-连通分支,其”势”较小。
对”势”相同的顶点来说,如果它不是割点,它们的最低深索数相同,且若有回边,其最低深索数等于所有回边连接的祖先中最先被深度优先搜索到的顶点的Order。若没有回边,其最低深索数等于其Order。
这样给出确定割点的条件:
若Low(w)>=Order(v),v不为根结点,其中w为v的某个孩子结点,则v为割点。
证明:如果”势”(w)=”势”(v),即w和v属于同一个2-连通分支如顶点F、G。此时若满足Low(w)=Order(v)!=Low(v),可知v为割点,如顶点F。
如果”势”(w)!=”势”(v),即w和v属于不同的2-连通分支,如顶点C、D。由w是v的孩子可知v为割点,如顶点C。此时对应的条件为Low(w)>Order(v),等价于Order(w)>Order(v)。
以下给出算法实现:
#include<iostream>
#include<stack>
using namespace std;
class side{
public:
side(int _b,int _e){b=_b;e=_e;}
int b;
int e;
};
class graph{
private:
int* adjacencylist;
int* visted;
int* order;
int* low;
int n;
int deep;
int get_value(int i,int j);
stack<side> s;
public:
graph(int num,int* adlist);
~graph();
void print_2_connected_graphs(int u,int v);
};
graph::graph(int num,int* adlist){
deep=1;
n=num;
adjacencylist=new int[n*n];
for(int i=0;i<n*n;i++) adjacencylist[i]=adlist[i];
visted=new int[n];
order=new int[n];
for(int i=0;i<n;i++) order[i]=0;
low=new int[n];
}
graph::~graph(){
delete [] adjacencylist; adjacencylist=NULL;
delete [] visted; visted=NULL;
delete [] order; order=NULL;
delete [] low; low=NULL;
}
int graph::get_value(int i,int j){
return adjacencylist[i*n+j];
}
void graph::print_2_connected_graphs(int u,int v){
order[u]=deep;
low[u]=deep;
deep=deep+1;
for(int w=0;w<n;w++){
//
if(get_value(u,w)!=0){
if(w!=v && order[w]<order[u]){
side tem_S(u,w);
s.push(tem_S);
}
/
if(order[w]==0){
print_2_connected_graphs(w,u);
///
if(low[w]>=order[u]){
while(true){
side temside=s.top();
s.pop();
cout<<"<"<<(char)(temside.b+'A')<<","<<char(temside.e+'A')<<"> ";
if((temside.b==u && temside.e==w)||(temside.b==w && temside.e==u)){
cout<<endl;
break;
}
}
}
///
low[u]=min(low[u],low[w]);
}
else if(w!=v){
low[u]=min(low[u],order[w]);
}
}
}
}
int main(int argc, char** argv){
int a[100]={0,1,0,0,0,1,0,0,0,0,
1,0,1,0,0,0,0,0,0,0,
0,1,0,1,1,1,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,1,0,0,0,0,0,0,0,
1,0,1,0,0,0,1,0,1,1,
0,0,0,0,0,1,0,1,1,1,
0,0,0,0,0,0,1,0,0,0,
0,0,0,0,0,1,1,0,0,1,
0,0,0,0,0,1,1,0,1,0};
graph g(10,a);
g.print_2_connected_graphs(0,-1);
}
运行结果:
<C,D>
<C,E>
<G,H>
<J,G> <J,F> <I,J> <I,F> <G,I> <F,G>
<F,A> <C,F> <B,C> <A,B>