求强联通分量有很多种。 《C++信息学奥赛一本通》  中讲过一个dfs求强联通分量的算法Kosdaraju,为了骗字数我就待会简单的说说。然而我们这篇文章的主体是Tarjan,所以我肯定说完之后再赞扬一下Tarjan大法好是不是

  首先我们讲一下强联通分量

  强联通分量指的是图的一个子图。在这个子图中,任意两个节点都可以互相到达。从定义上我们就可以看出是一个有向图来,因为任意一个无向图都符合该定义。

  而它的标准定义是:有向图中任意两点都联通的最大子图。

                    

  咳咳,首先庆祝一下哈——本人博客的第一张图。绘图历时3分钟。

  在咱们举的例子中,可以看出1 、2 、3 、5 通过边可以相互到达,它们算一个强联通分量,但4却被它们隔绝在外。从图中可以看出,从4点出发不能到达任意一个点。所以它单个节点也算一个强联通分量。所以图中的强联通分量有两个:一个是1-2-3-5,一个是4。

  ok看完了强联通分量是什么我们就讲一下Kosaraju。

  这个算法的思路是,对图进行DFS并记录每个点的退出顺序。再构造反图(就是有向边的方向全都反过来),按照退出顺序的逆序DFS反图,对得到的点进行染色即为强联通分量。

  讲完思路开始模拟。以起点1为起点遍历顺序如下:

  [ 1 2 3 5 4  5 3 2 4 4 1 ]

  加粗斜体外带下划线的部分就是本图的退出顺序。

  于是我们得到这样一个数组:[ 5 3 2 4 1 ] 。按照这个数组的逆序对反图遍历得到:

  [ 5 3 2 1 退出 4 退出 ]

  即得到要求的两个强联通分量。

  还要两遍DFS,麻烦的一比。看我大Tarjan一遍DFS就能求出强联通分量

  首先我们要明确Tarjan要用到的两个数组:dfn[] 和 low[]

  dfn指的是在DFS过程中访问到该点的顺序。从1开始DFS全图,那么1的dfn值就是1,2的dfn值是2,5的dfn值是4,4的dfn值是5。剩下的一个类推

  那么low呢?low指的是如果逆着DFS序往前回溯,该节点最早是由哪个节点走过来的。

  比如在上图中2 、3 、5 、4 最早都是由1走过来的,所以它们的low值都是1

  下面贴出dfn和low的算法

每次dfs(点u){

  dfn[u] = 进入 dfs() 函数的次数  (自己定义一个时间戳记录 如 time)

枚举与其相邻的点v{

       如果 没有 访问过点v {   ( 就是dfs树上的树边 )

        dfs(v);

        如果 v 能追溯 到 比“u 追溯到的最早的点” 更早的点;

        那么 u 就能 通过 v 来追溯到 那个点;

        low[u]=min(low[u],low[v]);

      }

      如果 访问过点v && v在栈中

       low[u]=min(low[u],dfn[v]);

}

  缩点

}

  上面那些伪代码是从伟大的GeneralLiu那里带过来的,在此先%%%

  然后  假设我们走到一个节点i,发现这个i不能继续扩展了,也就是dfn[i]==low[i]

  于是我们开始往回走。往回走的过程中,我们就把和它一个分量的节点进行染色,给它们统一的标记。  最后统计有多少种不同的标记即是强联通分量个数

  luogu的一道题刻录光盘非常好,可以用于练手。

  放代码

#include<iostream>
#include<cstring>
using namespace std;
int head[],num;
struct Edge{
int next,to;
}edge[];
int stack[],top;
int color[],cnt;
int dfn[],low[];
int ID;
bool jd[];
int vis[];
inline void add(int from,int to){
edge[++num]={head[from],to};
head[from]=num;
} void tarjan(int x){
dfn[x]=++ID;
low[x]=ID;
jd[x]=;
stack[++top]=x;
for(int i=head[x];i;i=edge[i].next){
int to=edge[i].to;
if(!dfn[to]){
tarjan(to);
low[x]=min(low[x],low[to]);
}
else if(jd[to]) low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x]){
jd[x]=;
color[x]=++cnt;
while(stack[top]!=x){
color[stack[top--]]=cnt;
jd[stack[top+]]=;
color[stack[top+]]=cnt;
}
top--;
} } int main(){
int n;
cin>>n;
int x;
for(int i=;i<=n;++i){
while(cin>>x&&x!=){
add(i,x);
}
}
for(int i=;i<=n;++i){
if(!dfn[i]) tarjan(i);
}
memset(jd,,sizeof(jd));
for(int i=;i<=n;++i){
for(int j=head[i];j;j=edge[j].next){
if(color[i]!=color[edge[j].to]){
jd[color[edge[j].to]]=;
}
}
}
int ans=;
for(int i=;i<=cnt;++i) if(!jd[i]) ans++;
cout<<ans<<endl;
return ;
}

Tarjan的强联通分量的更多相关文章

  1. tarjan求强联通分量

    tarjan求强联通分量 变量含义说明: pre[i]:i点的被访问的时钟编号,被分配后保持不变 low[i]:i点能访问的最先的点的时钟编号,随子节点改变 scc_no[i]:i点所在的强联通分量的 ...

  2. Tarjan求强联通分量+缩点

    提到Tarjan算法就不得不提一提Tarjan这位老人家 Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名.他拥有丰富的商业工作经验,1985年开始任教于普林斯顿大学.Tarj ...

  3. tarjan模板 强联通分量+割点+割边

    // https://www.cnblogs.com/stxy-ferryman/p/7779347.html ; struct EDGE { int to, nt; }e[N*N]; int hea ...

  4. USACO06JAN The Cow Prom /// tarjan求强联通分量 oj24219

    题目大意: n个点 m条边的图 求大小大于1的强联通分量的个数 https://www.cnblogs.com/stxy-ferryman/p/7779347.html tarjan求完强联通分量并染 ...

  5. Tarjan算法---强联通分量

    1.基础知识 在有向图G,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子 ...

  6. tarjan求强联通分量 模板

    void tarjan(int u) { dfn[u]=low[u]=++dfs_clock; stack_push(u); for (int c=head[u];c;c=nxt[c]) { int ...

  7. 培训补坑(day2:割点与桥+强联通分量)

    补坑ing... 好吧,这是第二天. 这一天我们主要围绕的就是一个人:tarjan......创造的强联通分量算法 对于这一天的内容我不按照顺序来讲,我们先讲一讲强联通分量,然后再讲割点与桥会便于理解 ...

  8. 【POJ 1236 Network of Schools】强联通分量问题 Tarjan算法,缩点

    题目链接:http://poj.org/problem?id=1236 题意:给定一个表示n所学校网络连通关系的有向图.现要通过网络分发软件,规则是:若顶点u,v存在通路,发给u,则v可以通过网络从u ...

  9. 强联通分量-tarjan算法

    定义:在一张有向图中,两个点可以相互到达,则称这两个点强连通:一张有向图上任意两个点可以相互到达,则称这张图为强连通图:非强连通图有极大的强连通子图,成为强联通分量. 如图,{1},{6}分别是一个强 ...

随机推荐

  1. UVA1607 Gates 与非门电路 (二分)

    题意:给你一个按发生时间的序列,表示与非门电路的输入,一开始全部输入是x,现在要改成尽量少的x,实现相同的功能. 题解:电路功能只有4中0,1,x,非x.那么如果一开始x改变了,输出结果不变,那么说明 ...

  2. CF Gym 100637A Nano alarm-clocks

    题意:给你一些钟的时间,只可以往后调, 问最少调的时间总和是多少 题解:因为肯定是调到某个出现过时间的,只要枚举时间,在维护一个前缀和快速计算出时间总和就行了. #include<cstdio& ...

  3. CSS选择器基本介绍

    一.web标准 所谓的web标准就是用来衡量我们当前的网页书写是否规范的一系列要求,这个标准是由W3C组织制定,在web标准中具体的要求就是结构.样式.行为三者相分离 结构:通过HTML标签来搭建的网 ...

  4. polygon 画图

    cityscape数据集,我现在想根据json文件中的polygon画出整个road的区域,这是运行的脚本.这个文件必须使用coco的pythonAPI的包,把这个脚本放在pythonAPI文件夹下就 ...

  5. UI Testing in Xcode 7

    参考文章: UI Testing in Xcode - WWDC 2015https://developer.apple.com/videos/play/wwdc2015-406/ Document ...

  6. virtualvenv+django+uWSGI+nginx 部署

    原创博文 转载请注明出处! 1. virtualvenv 2. django 3. uWSGI 4. nginx 5. 踩坑记录 1. virtualvenv virtualvenv install ...

  7. 对O(logN)复杂度的推导

    之前一直对O(logN)这个复杂度如何推导出的存在疑问,这段时间看了一些算法相关的内容,正好看到这个问题,大略研究了一下算是基本解答了我的疑惑:现记录如下 假设有一棵高为H的满二叉树,则它的节点共有N ...

  8. 【kmp】bzoj3620: 似乎在梦中见过的样子

    考察kmp理解题 Description “Madoka,不要相信 QB!”伴随着 Homura 的失望地喊叫,Madoka 与 QB 签订了契约. 这是 Modoka 的一个噩梦,也同时是上个轮回中 ...

  9. Golang 简单 http 代理转发

    程序基本实现了对http的完整转发,目前暂不支持https windows需要在设置中的网络>代理设置为手动,并开启代理服务器,填写ip和端口 // httpForward package ma ...

  10. Oracle 数据库常用SQL语句(2)查询语句

    一.SQL基础查询 1.select语句 格式:select 字段 from 表名; 2.where 用于限制查询的结果. 3.查询条件 > < >= <= = != 4.与 ...