有关概念:

  如果图中两个结点可以相互通达,则称两个结点强连通。

  如果有向图G的每两个结点都强连通,称G是一个强连通图。

  有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量。(这个定义在百科上和别的大神的博客中不太一样,暂且采用百科上的定义)

  Tarjan算法的功能就是求有向图中的强连通分量

思路:

  定义DFNi存放访问到i结点的次序(时间戳),Lowi存放i结点及向i下方深搜到的结点中能追溯到的访问次序最小的结点的访问次序(即这些结点回溯上去能找到的最小的DFN值),找到未被访问过的结点时进栈,当找到一个强连通分量的根结点时(判断条件DFNi==Lowi),将该结点到栈顶之间的元素退栈,作为一个强连通分量

  从结点1开始,枚举每一个未被访问的结点,以该节点为点u,进栈,赋DFNu=Lowu=time++,枚举每一个以u为起点的边,找到指向的终点v,进行判断:

  (1)v未被访问过,则以v为起点继续深搜,并做Lowu=min(Lowu,Lowv);

  (2)v仍在栈内,则做Lowu=min(Lowu,DFNv);(如果v的访问次序更小,更新Lowu,在回溯时更新u的父结点的Low值)

  枚举完毕后,判断该结点是否为某一强连通分量的根节点,是则进行退栈操作

样例推导:

从1开始深搜,1、2、4依次进栈

DFN={1,2,0,3,0,0}

搜索到4时有指向1的一条边,Low4=DFN1=1

6进栈

DFN={1,2,0,3,0,4}

判定 DFN6==Low6,6为第一个强连通分量的根节点,从6向栈顶(其实就一个元素)退栈,得第一个强连通分量为{6}

回溯到1,并更新Low值

DFN={1,2,0,3,0,4}

Low={1,1,0,1,0,4}

继续深搜到3,又有一条边指向4,Low3=DFN4=3

5进栈,有一条边指向6,但6被访问过且不在栈内,pass

此时5满足条件出栈,第二个强连通分量为{5}

回溯到1,更新Low值

DFN={1,2,5,3,6,4}

Low={1,1,3,1,6,4}

最后1满足条件,从1到栈顶出栈,第三个强连通分量为{1,2,3,4}

复杂度:

  每一个点和边均只被访问过一次,时间复杂度为O(n+m)

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN
#define MAXM
int n,m,time,cnt,heads[MAXN],DFN[MAXN],Low[MAXN],stack[MAXN],top,belong[MAXN];//time为访问次序,belong存该结点属于第几个强连通分量
bool vis[MAXN];//该结点是否在栈内
struct node
{
int v,next;
}edge[MAXM];
void add(int x,int y)
{
edge[++cnt].next=heads[x];
heads[x]=cnt;
edge[cnt].v=y;
}
void tarjan(int u)
{
DFN[u]=Low[u]=++time;
vis[u]=true;
stack[++top]=u;//进栈
for(int i=heads[u];i!=;i=edge[i].next)
{
int v=edge[i].v;
if(!DFN[v])//是否被访问过,DFN初值都为0,只有访问过才会被赋值
{
tarjan(v);
Low[u]=min(Low[u],Low[v]);
}
else if(vis[v])Low[u]=min(Low[u],DFN[v]);
}
if(DFN[u]==Low[u])//该结点为根结点,出栈
{
int i;
cnt++;
do
{
i=stack[top--];
vis[i]=false;
belong[i]=cnt;
print();//输出之类的操作
}while(u!=i);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);//默认输入有向边
}
cnt=;//cnt为强连通分量数量
for(int i=;i<=n;i++)
if(!DFN[i])tarjan(i);
return ;
}

*参考:http://baike.baidu.com/link?url=3xvU8jjqA2McnNL07G_5XHs8so96ZLAwjmc5oMPY1K67EkixIzyHdrn6QhqCsM9da0SVN_9vvca4iEcXJMyRVK

图论-强连通分量-Tarjan算法的更多相关文章

  1. 有向图强连通分量Tarjan算法

    在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...

  2. 有向图强连通分量 Tarjan算法

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...

  3. [有向图的强连通分量][Tarjan算法]

    https://www.byvoid.com/blog/scc-tarjan 主要思想 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的 ...

  4. 图之强连通、强连通图、强连通分量 Tarjan算法

    原文地址:https://blog.csdn.net/qq_16234613/article/details/77431043 一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶 ...

  5. 求图的强连通分量--tarjan算法

    一:tarjan算法详解 ◦思想: ◦ ◦做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间 ...

  6. POJ1236_A - Network of Schools _强连通分量::Tarjan算法

    Time Limit: 1000MS   Memory Limit: 10000K Description A number of schools are connected to a compute ...

  7. poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

    题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Sub ...

  8. 强连通分量--tarjan算法

    今天学了一个强连通分量,用tarjan做.北京之前讲过,今天讲完和之前一样,没有什么进步.上课没听讲,只好回来搞,这里安利一个博客:链接 https://blog.csdn.net/qq_343746 ...

  9. 强连通分量——tarjan算法

    概念: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通.如果有向图G的每两个顶点都强连 ...

随机推荐

  1. BZOJ 1082 栅栏(二分+DFS剪枝)

    首先,长度短的木板一定比长度长的木板容易得到,因此若要得到最多的木板,它们必定是所有木板中最短的——可以对木板排序后二分答案(用k表示). 判断是否合法就用搜索,但数据有点大,要用到两个剪枝.一个是若 ...

  2. 【bzoj4922】[Lydsy六月月赛]Karp-de-Chant Number 贪心+背包dp

    题目描述 给出 $n$ 个括号序列,从中选出任意个并将它们按照任意顺序连接起来,求以这种方式得到匹配括号序列的最大长度. 输入 第一行包含一个正整数n(1<=n<=300),表示括号序列的 ...

  3. 【bzoj1609】[Usaco2008 Feb]Eating Together麻烦的聚餐 dp

    题目描述 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的位置就归第2批 ...

  4. android应用打前需要准备些啥?

    发布之前我们需要准备的东西 参考了google官方和结合国内开发经验 1) 用户协议(本地.网络.API) 2) 签名文件(用于为APP加密,唯一标签) 3) 程序图标(第一个面对用户,准备不同的但合 ...

  5. 【刷题】洛谷 P2709 小B的询问

    题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重 ...

  6. 分享几款常用的API/文档浏览器

    1.Dash 支持平台:Mac  iOS 官网:https://kapeli.com/dash 2.Zeal 支持平台:Linux Windows 官网:https://zealdocs.org/ G ...

  7. javascript实现deepEqual和shallowEqual

    function deepEqual(x, y) { if (x === y) { return true; } if (!(typeof x == "object" && ...

  8. NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第一轮Day2题解

    上星期打的...题有点水,好多人都AK了 T1排个序贪心就好了 #include<iostream> #include<cstring> #include<cstdlib ...

  9. python获取当前工作目录

    py文件所在位置/test/pj/hello.py 用户所在位置:/ 用户执行命令python /test/pj/hello.py 1. os.getcwd() 返回的是执行命令的位置 / 2.sys ...

  10. mybaties实体的 Mapper.xml文件中自定义sql时模糊查询的写法

    <select  id=selectByNameLike" parameterType="string" resultMap="BaseResultMap ...