双连通分量(DCC)

来源:互联网 发布:vue.js 页面加载动画 编辑:程序博客网 时间:2024/06/09 16:50

求双连通分量(tarjan方法)

解释都在代码里:

#include<iostream>#include<cstdio>#include<cstring>#define CLR(a,b) memset(a,b,sizeof(a))#define Min(a,b) a>b?b:ausing namespace std;const int INF=1e5+5;int dfn[INF];          //记录各结点的访问次序int low[INF];          //low是追溯到DCC的根节点的dfn的值                       //当根节点的某个直接儿子节点的low值大于或等于根节点的dfn的值时,                       //就可以从栈中取值了,直到取到根节点为止时就是一个DCC  int dcc_id[INF];      //存储各节点的所在的编号(就是你给他们编的号,从1到n)cnt_dcc就是编号下标!  int stack[INF];       //栈:用深搜搜索节点并依次存储各个节点—以便于找到DCC                      //即当发现环时就是一个DCC,用low标记的,从该栈中取值取到该根节点为止 int father[INF];      //由于求DCC是在一个无向连通图中,即为双向的图                      //该father就是为了防止某一节点又访问上一个节点(上一个节点搜出该节点)  int top,cnt_dcc,cnt_idex;struct Edge         //存储边的信息{    int to;    Edge *next;};Edge *edge[INF];void tarjan(int u){    dfn[u]=low[u]=++cnt_index;    stack[++top]=u;    for(Edge *temp=edge[u];temp;temp=temp->next)    {        int v=temp->to;        if(!dfn[v])        {            father[v]=u;            tarjan(v);            low[u]=Min(low[u],low[v]);    //更新low使每一个DCC中的low的值==根节点low值              if(low[v]>=low[u])           //当发现节点u的儿子节点v的low值>=dfn[u]              {                            //则就要取栈,即是时候取出DCC了                cnt_dcc++;                int j;                do                {                    j=stack[top--];                    dcc_id[j]=cnt_dcc;                }while(v!=j);                top++;                  //这里为什么要++?因为连着DCC是有共同节点的            }        }        else if(v!=father[v])            low[u]=Min(low[u],dfn[v]);    }}void solve(int node)        //node 为要深搜的结点{    top=cnt_dcc=cnt_idex=0;    CLR(dfn,0);    tarjan(node);        //由于是无向连通图,只需深搜一个节点就都可以都到了  }


原创粉丝点击