[算法定义]

在有向图中,如果两个顶点至少存在一条路径(可以相互通达),则称两个顶点强连通(strongly connected)。

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

非强连通有向图的极大强连通子图,称为强连通分量(strongly connected components)。

在上图中,{1 , 2 , 3 , 4 } , { 5 } ,  { 6 } 三个区域可以相互连通,称为这个图的强连通分量。

Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。

DFN[ i ] : 在DFS中该节点i被搜索的次序(时间戳)。

LOW[ i ] : 为i或i的子树能够追溯到的最早的栈中节点的次序号。

当DFN[ i ]==LOW[ i ]时,已i为根的搜索子树上所有节点是一个强连通分量。

【心得】:如果有环,dfn是传递自己的下一代,low是继承自己的上一代或自己(上一代无环)

搜索时,把当前搜索树中未处理的节点加入一个堆栈。

回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。


[算法图解]

从1开始dfs搜索,把遍历到的节点加入栈中。

搜索到i=6时,节点都入栈了,此时就进行回溯。

DFN[6]=LOW[6],以节点6为根的搜索子树是一个强连通分量(节点6没有子树)。

6出栈。


依次类推,DFN[5]=LOW[5],5为强连通分量

并且5的边也都找完了,5出栈。

接下来回溯到3,4入栈。


然后从4找到1,发现节点1已存在。

将1看做根节点往回搜索子节点,子节点LOW[i]=low[根]=1。

子节点low继承的是根的dfn,根的low就是根的dfn,最小的那个

现在只是将1,3,4看做环,1的边还没有找完。

没有找完自然不会进行根节点1成环的回溯出栈操作。


继续找1的边,找到2。

再访问4(还在栈中),所以LOW[2]=DFN[4]=5。

那么4的根是2,为什么不继承1的dfn,是为了让缩点与割点代码一致

结果不影响,连通分量还是一起出栈(并染色)

从2返回1后,发现DFN[1]=LOW[1],把栈中节点全部取出,组成一个强连通分量{1,2,3,4}。

【例】如果2跟1不成环,那么2不会连4,(2将自己抛出)或(2与2的子节点成环整个抛出)

最后执行到1,再进行1的回溯,组成强连通分量{1,3,4}出栈


自此算法结束,找到{1,2,3,4},{5},{6}三个强连通分量


[代码1]不要慌全解系列

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;struct ss{int v;int next;/*  v指节点v next永远指u点->上一个点的边序(1,2,3···)边序 即u到其他点(上一个点)是第几条边(num) 上一条边没有就是-1 */
}s[1000]; int head[1000];//边序
int dfn[1000];
int low[1000];
int vis[1000];//相当于栈
int color[1000];//染色
int n,m;
int cnt;
int num;
stack<int >st;void init()
{memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));//memset(color,0,sizeof(color));    num=0;cnt=0;
}
void add(int u,int v)
{s[num].v = v;s[num].next = head[u];head[u] = num++;/*将v存进去将u->上一个点的边序挂上nextnum一直在++(总边数不会错)head[u]更新当前u的边序           如果双向再存u挂v边序 eg[num].v = u;eg[num].next = head[v];head[v] = num++;*/
}
void Tarjan(int u)
{st.push(u);dfn[u] = low[u] = ++cnt;//搜索次序号 vis[u]=1;//节点x在栈中for(int i = head[u]; i != -1; i = s[i].next){//通过对u点上一个边序的挂钩//构造对连接u点的所有边数遍历查找对应v点 int v = s[i].v;if(!dfn[v])//不曾访问过 {Tarjan(v);//找v点 low[u] = min(low[u],low[v]);/* 根节点的dfn值是区分不同环的值low是为了让这个环都等dfn[根]low[根]可能不等dfn[根]根的low继承根的根的dfn 1.如果v是根节点不论只有v一个点还是有一个环 low[v]确实永远比low[u]大(u比v先入)v的环low值=dfn[v]都比low[u]的大 v不对u产生影响2. 如果v点与u点成环那么顺着v点或v连着的点找下去总有一个能连到根节点low值回溯的时候继承根的dfn值根的dfn是这个环里面最小的low[v]等于dfn[根]v对u产生影响->low[u]=low[v] */ }else if(vis[v])//访问过但还在栈中 /*因为根u点还没有将边都找完出栈的点都是根节点边已经找完的点或者环 已经没有与剩下的点有任何关系才能出 */ low[u] = min(low[u],dfn[v]);/*这相当于根节点有两个分叉口a,b 并且a找到已经在栈中的b那么这一步其实也可以写成 low[u] = min(low[u],low[v]);反正连到一个环了目的是为了让缩点与割点的代码一致 区分相连的环的根有不同的dfn无向图找割点用的但是缩点是将一起出栈的点缩成一个点(染成一个色)对于缩点结果都无影响   */} if(dfn[u]==low[u])//找一遍再是强连通分量 {int now;do{   //取出包括u的环 now=st.top();color[now]=u; //染色 vis[now]=0;st.pop();}while(now!=u);}return;
}
void out()
{for(int i=1;i<=n;i++)printf("%d ",i);printf("\n");for(int i=1;i<=n;i++)printf("%d ",color[i]);printf("\n");
}int main()
{while(~scanf("%d%d",&n,&m) && (m+n)){init();int u,v;while(m--){scanf("%d%d",&u,&v);   add(u,v);}  //为了防止一个图里有不相连的两个或多个树 for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);out();} return 0;
} 

[代码2]

若只是缩点,求强连通分量染色,不与割点代码一致,就不需要用栈

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;int dfn[1000];
int low[1000];//就相当于颜色,一个环一个low=dfn[根]
int vis[1000];
int n,m;
int cnt;
stack<int >st;
vector<int >vc[1000]; void init()
{memset(vis,0,sizeof(vis));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low)); cnt=0;
}void Tarjan(int u)
{st.push(u);dfn[u] = low[u] = ++cnt;vis[u]=1;for(int i = 0; i < vc[u].size(); i++){int v = vc[u][i];if(!dfn[v]){Tarjan(v);low[u] = min(low[u],low[v]);}else low[u] = min(low[u],low[v]);  } return;
}
void out()
{for(int i=1;i<=n;i++)printf("%d ",i);printf("\n");for(int i=1;i<=n;i++)printf("%d ",low[i]);printf("\n");
}int main()
{while(~scanf("%d%d",&n,&m) && (m+n)){init();int u,v;while(m--){scanf("%d%d",&u,&v);   vc[u].push_back(v);}    for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);out();} return 0;
} 

Tarjan求强连通分量相关推荐

  1. hdu 1269 tarjan求强连通分量

    tarjan求强连通分量的裸题复习,可当做模板. 1 #include <stack> 2 #include <cstdio> 3 #include <cstring&g ...

  2. The King’s Problem(tarjan求强连通分量缩点+匈牙利求有向无环图的最小路径覆盖)

    Link:http://acm.hdu.edu.cn/showproblem.php?pid=3861 The King's Problem Time Limit: 2000/1000 MS (Jav ...

  3. 洛谷 P2921 在农场万圣节Trick or Treat on the Farm (tarjan求强连通分量)

    洛谷 P2921 在农场万圣节Trick or Treat on the Farm (tarjan求强连通分量) 题目描述 每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N&l ...

  4. hdu 1269(Tarjan求强连通分量)

    这道题目就是求强连通分量... 这里采用的是Tarjan算法:http://m.blog.csdn.net/blog/qq574857122/16361033 AC代码: #include<io ...

  5. HDU-1269 Tarjan求强连通分量,模板题

    HDU 1269 题意:n个点m条单向边,问任意两个点是否连通. 总结:参考大神博客码的,有些地方还是不太明白. 而且这题还可以双向dfs做,有时间再做一下. // HDU-1269 #include ...

  6. 【HDU - 4635】Strongly connected(缩点,新图性质,建图,Tarjan求强连通分量)

    题干: Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the ...

  7. 图论 —— 图的连通性 —— Tarjan 求强连通分量

    [概述] Tarjan 算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树. 搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量. [ ...

  8. P1262 间谍网络 (Tarjan 求强连通分量)

    题目传送门:https://www.luogu.com.cn/problem/P1262 题意 题意转换成图的角度理解,给出初始可以访问的节点 D i D_i Di​ 以及访问这些节点需要的代价 W ...

  9. tarjan求强连通分量的思考

    我是按照这里的思路来的.这个博文只是感性理解. 递归树 关于递归树,这篇博文讲的很好,我只是给自己总结一下. 定义vis数组,在dfs连通图时赋予它们不同的含义: vis=0,表示这个点没有被访问. ...

最新文章

  1. Mysql 安装服务无法启动解决方案与使用的一般使用指令
  2. 使用numba要注意的越界问题
  3. python 文件操作 os.readline()函数用法
  4. JavaScript实用小技巧
  5. kde下sudo出现cannot connect to xserver解决方法
  6. jQuery plugin 开发的一个例子
  7. ubuntu下安装chrome浏览器和flash插件
  8. Socket相关操作超时
  9. WPS关于尾注的细节
  10. python爬取小说网站资源_利用python的requests和BeautifulSoup库爬取小说网站内容
  11. esxi时区设置 +8_ESXI安装OpenWRT amp; LEDE软路由部署指南(附镜像下载)
  12. 《Java项目开发案例整合》
  13. java面向对象数组实现家庭收支记账软件_C项目-家庭收支记账软件
  14. springboot配置https
  15. 移动应用专项测试的思路和方法
  16. 基于网格化的主干光缆纤芯配置模型
  17. C语言枚举变量定义,请问C语言枚举类型是什么意思
  18. 再见c罗再见梅西_再见眼镜你好smartglasses
  19. R WinBugs network meta analysis
  20. Java毕设项目户籍管理系统(java+VUE+Mybatis+Maven+Mysql)

热门文章

  1. 计算机创新创业2000字,创新创业论文范文 创新创业方面硕士毕业论文范文2000字...
  2. react 脚手架创建后暴漏配置文件 运行yarn eject 报错 (已解决)
  3. bullet3 代码结构梳理
  4. 高校企业双向赋能,首届飞桨启航菁英计划圆满结束
  5. Oracle导入英文日期格式数据出现问题的解决
  6. Spring Boot 动态设置数据库密码,密码加密,密码单独处理
  7. scp传文件指定端口、传输目录
  8. 自然语言处理技术及处理框架学习
  9. 中国农业机械融资租赁市场预测与投资战略报告(2021版)
  10. 排序刷默认值sql脚本