现在的位置: 首页 > 综合 > 正文

Tarjan算法模板 详解

2018年03月17日 ⁄ 综合 ⁄ 共 1711字 ⁄ 字号 评论关闭
思想:

做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间。初始时dfn[i]=low[i]

在DFS过程中会形成一搜索树。在搜索树上越先遍历到的节点,显然dfn的值就越小。

DFS过程中,碰到哪个节点,就将哪个节点入栈。栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈。

如果发现某节点u有边连到搜索树中栈里的节点v,则更新u的low 值为dfn[v](更新为low[v]也可以)。
如果一个节点u已经DFS访问结束,而且此时其low值等于dfn值,则说明u可达的所有节点,都不能到达任何在u之前被DFS访问的节点
---- 那么该节点u就是一个强连通分量在DFS搜索树中的根。

此时将栈中所有节点弹出,包括u,就找到了一个强连通分量

以poj 1236 Network of Schools 为例说明

192K   
0MS
#include <string.h>
#include <stdio.h>
#define V   
105
#define E   
100500

struct edge
{
    int to,
next;
}Edge[E];
int head[V], e, n;

int indeg[V], outdeg[V]; //点的入度和出度数
int belong[V], low[V], dfn[V], scc, cnt;//dfn[]:遍历到u点的时间;
low[]:u点可到达的各点中最小的dfn[v]
int S[V], top;
bool vis[V];//v是否在栈中

int addedge(int u, int v)
{
    Edge[e].to =
v;
    Edge[e].next
= head[u];
    head[u] =
e++;
    return
0;
}
void tarjan(int u)
{
    int v;
    dfn[u] =
low[u] = ++cnt;//开始时dfn[u] == low[u]
    S[top++] =
u;//不管三七二十一进栈
    vis[u] =
true;
    for (int
i=head[u]; i!=-1; i=Edge[i].next)
    {
   
    v =
Edge[i].to;
   
    if (dfn[v]
== 0)//如果v点还未遍历
   
    {
   
   
   
tarjan(v);//向下遍历
   
   
    low[u] =
low[u] < low[v] ? low[u] : low[v];//确保low[u]最小
   
    }
   
    else if
(vis[v] && low[u] >
dfn[v])//v在栈中,修改low[u]
   
   
    low[u] =
dfn[v];
    }
    if (dfn[u]
== low[u])//u为该强连通分量中遍历所成树的根
    {
   
    ++scc;
   
    do
   
    {
   
   
    v =
S[--top];//栈中所有到u的点都属于该强连通分量,退栈
   
   
    vis[v] =
false;
   
   
    belong[v] =
scc;
   
    } while (u
!= v);
    }

}

int solve()
{
    scc = top =
cnt = 0;
    memset(dfn,
0, sizeof(dfn));
    memset(vis,
false, sizeof(vis));
    for (int
u=1; u<=n; ++u)
   
    if (dfn[u]
== 0)
   
   
   
tarjan(u);
    return
scc;
}

void count_deg()
{
   
memset(indeg, 0, sizeof(indeg));
   
memset(outdeg, 0, sizeof(outdeg));
    for (int
u=1; u<=n; ++u)
   
    for (int
i=head[u]; i!=-1; i=Edge[i].next)
   
    {
   
   
    int v =
Edge[i].to;
   
   
    if
(belong[u] != belong[v])
   
   
    {
   
   
   

抱歉!评论已关闭.