重连通分量

来源:互联网 发布:如何安装网络监控 编辑:程序博客网 时间:2024/05/01 21:58

所谓重连通图(点双连通图)是指不存在割点的图。

重连通分量即为原图的极大重连通图,相当于把原图划分成若干个重连通图(可相交),交点是割点。

求解过程是模仿割点的求解算法,但又有些不同,即low数组有区别,因为每条边只会被访问一次,也就是说b是a的孩子节点,那么访问b时不会再访问边ba,这样也就是low[b]缺少了dfn[a]的更新,但这并不影响该点是否是割点,因为不是割点取决于low[b]<dfn[a],即b出来的回边要到达b的祖先(不包括双亲),于是可以看出两种做法不影响求解割点。

但后者可以保证每条边访问一次,于是利用一个栈不停压入访问的边,直到出现割点,此时退栈直到割点沿此孩子下去的边,这个就是一个重连通分量。如此,操作直到栈为空。

根节点并没有此性质,但压栈过程让我们看到,如果虚拟一个根节点的父亲节点,那么根节点也可以同样处理,但是代码中不需要体现虚拟节点,只需要在大脑中想像。

这个也就是为什么根节点要大于1个孩子,而非根节点只要一个孩子(满足low>=dfn这个条件)的原因,因为你可以把非根节点的父亲看成他的另一颗子树,这样low>=dfn也就是没有分叉边,这就完全和根节点一样了(分叉边不在原图中存在)。


#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define MAXN 20#define MAXM 40using namespace std;struct edge{    int u,v;    void output(){printf("%d->%d",u,v);}    int comp(edge t){        return (u==t.u&&v==t.v)||        (u==t.v&&v==t.u);    }}edges[MAXM];int se;int Edge[MAXN][MAXN];int vis[MAXN];int n,m;int tmpdfn;int dfn[MAXN];int low[MAXN];void dfs(int u){    for(int v=1;v<=n;v++){        if(Edge[v][u]==1){            edge t;            t.u=u,t.v=v;            edges[++se]=t;            Edge[v][u]=Edge[u][v]=2;            if(!vis[v]){                vis[v]=1;                tmpdfn++;                dfn[v]=low[v]=tmpdfn;                dfs(v);                low[u]=min(low[u],low[v]);                if(low[v]>=dfn[u]){                    bool firstedge=true;                    while(1){                        if(se<0) break;                        if(firstedge) firstedge=false;                        else printf(" ");                        edge t1;                        t1=edges[se];                        t1.output();                        se--;                        if(t1.comp(t)) break;                    }                    puts("");                }            }            else low[u]=min(low[u],dfn[v]);    }}}int main(){    int u,v;    int number=1;    while(1){        cin>>n>>m;        if(n==0&&m==0) break;        memset(Edge,0,sizeof Edge);        for(int i=1;i<=m;i++){            cin>>u>>v;            Edge[u][v]=Edge[v][u]=1;        }        if(number>1) puts("");        number++;        low[1]=dfn[1]=1;        tmpdfn=1;        memset(vis,0,sizeof vis);        vis[1]=1;        se=-1;        dfs(1);    }    return 0;}

测试数据:

7 9
1 2
1 3
1 6
1 7
2 3
2 4
2 5
4 5
6 7
4 4
1 2
2 3
3 4
4 1
0 0

输出:

5->2 4->5 2->4
3->1 2->3 1->2
7->1 6->7 1->6

4->1 3->4 2->3 1->2


0 0
原创粉丝点击