zoukankan      html  css  js  c++  java
  • Tarjan的求双连通分量算法

    哎~气死我了!昨天晚上都写好了……一不小心把网页关了,写的全没了……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的值时,就可以从
    //栈中取值了,直到取到根节点为止时一个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,有时候要求割点,求桥,你根据定义自己想想……都差不来啊!

    可能解释的不够清楚,有什么问题?可以问我饿!或者发现有什么不对或不好的地方,欢迎指正!

    不过我也只是知道这样实现,并不真正懂得为什么。你如果问我为什么是这样,它的原理是什么?我会给你说:因为只有这样才能实现,它原理就在实现中^_^!如果大虾你理解的深的话……希望能给小弟分享一下!

  • 相关阅读:
    mysql面试知识点
    计算机网络
    BFS
    拓扑排序
    双指针
    回溯算法
    hash表 算法模板和相关题目
    桶排序及其应用
    滑动窗口
    贪心算法
  • 原文地址:https://www.cnblogs.com/fornever/p/2179448.html
Copyright © 2011-2022 走看看