双连通分量求解===

最近面阿里实习生===在第二个电面后被刷了,也怪自己操作系统学得不好。。。现在要好好看看数据结构、操作系统、算法好好看一下===

下面给出双连通分量求解===

什么是双连通分量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的值时,就可以从
//栈中取值了,直到取到根节点为止时一个DCC

int 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);//由于是无向连通图,只需深搜一个节点就都可以都到了
}

上面的是求DCC,有时候要求割点,求桥,你根据定义自己想想……都差不来啊!

 

来源网站:http://www.cnblogs.com/fornever/archive/2011/09/17/2179448.html

你可能感兴趣的:(算法图论Tarjin双连通分量)