TARJAN的求双连通分量算法

来源:互联网 发布:libevent源码解析 编辑:程序博客网 时间:2024/05/16 19:13

转自:  http://www.cnblogs.com/fornever/archive/2011/09/17/2179448.html

哎~气死我了!昨天晚上都写好了……一不小心把网页关了,写的全没了……MD

什么是双连通分量DCC(Double connected component)?

首先说一下一个无向连通图,若去掉任一点或任一边都不影响该图的连通性(本来是连通的,现在仍连通),那么该图是一个双连通图(该图的DCC只有一个即本身)。

DCC是一个无向连通图(注意是无向连通图不是有向图,别把强连通分量与他们搞混了!)的子图,该子图是一个双连通图(尽可能大的双连通图,也就是尽可能包含更多的点)。也就是说一个无向连通图的DCC需要满足三个条件:1.它是该无向连通图的子图 2.该子图是一个双连通图 3.使该子图尽可能的大

什么是割点、桥?

一个无向连通图,去掉一点或一边后影响了改图的连通性(本来是连通的,现在不连通了),则该点就是割点或该边就是桥。

求DCC的算法的分析,我就不说了……就是说了也难以理解,直接贴上加注释的code,你自己画个图,跟着程序走一遍,慢慢体会体会!

//----------DCC------------------int dfn[MAXNODE],low[MAXNODE],index;//dfn记录各点被访问次序,low是追溯到DCC的根节点//的dfn的值,当根节点的某个直接儿子节点的low值大于或等于根节点的dfn的值时,就可以从//栈中取值了,直到取到根节点为止时一个DCCint stack[MAXNODE],top;//栈:用深搜搜索节点并依次存储各个节点—以便于找到DCC(即当//发现环时就是一个DCC,用low标记的,从该栈中取值取到该根节点为止)int id_dcc[MAXNODE],cnt_dcc;//id_dcc:名副其实即DCC的id(编号),存储各节点的所在的//编号(就是你给他们编的号,从1-n)cnt_dcc就是编号下标!int father[MAXNODE];//由于求DCC是在一个无向连通图中,即为双向的图,该father就是为了//防止某一节点又访问上一个节点(上一个节点搜出该节点)void DFS_DCC(int cur){    int next;                      //next为cur节点下的节点     dfn[cur]=low[cur]=++index;    stack[++top]=cur;    for(Node *p=G[cur];p;p=p->next)    {        next=p->num;        if(!dfn[next])        {            father[next]=cur;      //额,可以不用。。              DFS_DCC(next);            if(low[next]<low[cur]) //更新low使每一个DCC中的low的值==根节点low值                low[cur]=low[next];            if(low[next]>=dfn[cur])//当发现节点cur的儿子节点next的low值>=dfn[cur]            {                      //则就要取栈,即是时候取出DCC了。为什么?因为不                cnt_dcc++;           //这样就不对了^_^!(具体原因,自己举几个例子try)                do              {                 next=stack[top--];                 id_dcc[next]=cnt_dcc;              }while(next!=cur);              top++;               //这里为什么要++因为连着DCC是有共同节点的(举例try)                                        //不++肯定要出错!也许我这code跟别人不一样,其实                                       //思想都一样,只是具体实现的code有小小的差异罢了            }        }        else if(next!=father[cur] && dfn[next]<low[cur])        {                                  //呃呃呃!其实不用这个father数组都可以了,只需                                      //dfn[next]<low[cur]就行了             low[cur]=dfn[next];        }                }}void solve(){    index=top=cnt_dcc=0;    memset(dfn,0,sizeof(dfn));//初始化各下标及dfn    DFS_DCC(1);//由于是无向连通图,只需深搜一个节点就都可以都到了}


原创粉丝点击