【原创】tarjan算法初步(强连通子图缩点)

tarjan算法的思路不是一般的绕!!(不过既然是求强连通子图这样的回路也就可以稍微原谅了。。)

但是研究tarjan之前总得知道强连通分量是什么吧。。

上百度查查:

  有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。

看不懂。。那么——

看这张图

其中从1可以到2,3,4,5,6;

从2可以到1,3,4,5,6;

从3可以到6;

从4可以到1,2,3,5,6;

从5可以到1,2,3,4,6;

从6哪儿都到不了。

我们发现,{1,2,4,5}两两可以互达,我们称其为原图的一个强连通子图,而{3},{6}各自单独为原图的另外两个强连通子图。

我们想要通过程序实现O(n)求所有强连通子图,就要用到tarjan算法。

程序代码如下(tarjan的主要思路写在程序注释里,若无法理解请参考另一篇【转载】全网最!详!细!tarjan算法讲解):

 // Tarjan有向图强连通缩点
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<string>
#define MAXV 10010
#define MAXE 100010
using namespace std;
struct tEdge{
int np;
tEdge *next;
}E[MAXE],*V[MAXV];
int tope=-;
int n,m;
int dfn[MAXV],dfstime=; // dfn[i]表示点i的dfs序
int low[MAXV]; // low[i]表示目前点i所能到达的最小dfs序点
int status[MAXV]; // status[i]表示点i的访问状态,0=未访问,1=访问中,2=访问完毕
int stack[MAXV],tops=-;
int color[MAXV],totc=; // color[]表示缩点后的块
void addedge(int u,int v){
E[++tope].np=v;
E[tope].next=V[u];
V[u]=&E[tope];
}
void tarjan(int now){
stack[++tops]=now; // 进栈
low[now]=dfn[now]=++dfstime; // 初始化dfs序
status[now]=; // 访问中(在栈中)
for(tEdge *ne=V[now];ne;ne=ne->next){
if(status[ne->np]==){ // 未访问(没有进过栈)
tarjan(ne->np); // dfs往下进行递归访问
low[now]=min(low[now],low[ne->np]);
// 由于now可达ne->np,故ne->np可达的最小dfs序点从now也可达
}
else if(status[ne->np]==){ // 回边,发现ne->np为栈中元素
low[now]=min(low[now],dfn[ne->np]);
// 若ne->np的dfs序比原来now可达的最小dfs序还小则更新
}
}
if(low[now]==dfn[now]){
// now到达的最小dfs序为自己dfs序
// 即now不包含在最小dfs序更小的缩点中
// 而栈中now以后的节点若不能到达now则早已出栈(FILO)
totc++; // 申请新颜色(一种颜色代表一个缩点)
while(stack[tops+]!=now){ // 栈中所有在now之后的节点都在该缩点内
status[stack[tops]]=; // 访问完毕(已出栈)
color[stack[tops--]]=totc; // 为节点染色
}
}
}
int main(){
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(status,,sizeof(status));
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
}
for(int i=;i<=n;i++)
if(status[i]==)
tarjan(i); // 图不连通时必须保证每个点都处理到
for(int i=;i<=n;i++)
printf("Point %d colored %d\n",i,color[i]); // 输出所属强连通块编号
return ;
}

测试数据:


运行结果:

Point  colored
Point colored
Point colored
Point colored
Point colored
Point colored

即color[1]={6},color[2]={3},color[3]={1,2,4,5}为原图的3个强连通子图的缩点。

【原创】tarjan算法初步(强连通子图缩点)的更多相关文章

  1. Tarjan算法分解强连通分量(附详细参考文章)

    Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...

  2. tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)

    这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...

  3. Tarjan算法初步

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

  4. Tarjan在图论中的应用(一)——用Tarjan来实现强连通分量缩点

    前言 \(Tarjan\)是一个著名的将强连通分量缩点的算法. 大致思路 它的大致思路就是在图上每个联通块中任意选一个点开始进行\(Tarjan\)操作(依据:强连通分量中的点可以两两到达,因此从任意 ...

  5. [学习笔记] Tarjan算法求强连通分量

    今天,我们要探讨的就是--Tarjan算法. Tarjan算法的主要作用便是求一张无向图中的强连通分量,并且用它缩点,把原本一个杂乱无章的有向图转化为一张DAG(有向无环图),以便解决之后的问题. 首 ...

  6. HDU 1269 迷宫城堡 tarjan算法求强连通分量

    基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...

  7. Tarjan算法【强连通分量】

    转自:byvoid:有向图强连通分量的Tarjan算法 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断 ...

  8. Tarjan 算法求 LCA / Tarjan 算法求强连通分量

    [时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...

  9. 【算法】Tarjan算法求强连通分量

    概念: 在有向图G中,如果两个定点u可以到达v,并且v也可以到达u,那么我们称这两个定点强连通. 如果有向图G的任意两个顶点都是强连通的,那么我们称G是一个强连通图. 一个有向图中的最大强连通子图,称 ...

随机推荐

  1. Linux 网络工具netcat(nc)的应用

    NETCAT netcat是Linux常用的网络工具之一,它能通过TCP和UDP在网络中读写数据,通过与其他工具结合和重定向,可以在脚本中以多种方式使用它. netcat所做的就是在两台电脑之间建立链 ...

  2. 第6章:使用Python监控Linux系统

    1.Python编写的监控工具 1).多功能系统资源统计工具dstat dstat是一个用Python编写的多功能系统资源统计工具,用来取代Linux下的vmstat,iostat,netstat和i ...

  3. 植物大战僵尸:寻找召唤僵尸关键CALL

    实验目标:通过遍历寻找召唤僵尸的CALL,通过调用CALL出现自定义的僵尸,加速僵尸的出现. 僵尸CALL的遍历技巧: 我们可以通过僵尸出现在屏幕中的个数来遍历寻找僵尸出现的CALL 首先打开CE-& ...

  4. 使用haystack实现django全文检索搜索引擎功能

    前言 django是python语言的一个web框架,功能强大.配合一些插件可为web网站很方便地添加搜索功能. 搜索引擎使用whoosh,是一个纯python实现的全文搜索引擎,小巧简单. 中文搜索 ...

  5. redhad 7.0更换yum源

    1.  卸载红帽yum源 rpm –e $(rpm –qa|grep yum) --nodeps 2.删除所有repo相关文件 rm –rf /etc/yum.conf rm –rf /etc/yum ...

  6. 超详细,新手都能看懂 !使用SpringBoot+Dubbo 搭建一个简单的分布式服务

    来自:JavaGuide Github 地址:https://github.com/Snailclimb/springboot-integration-examples 目录: 使用 SpringBo ...

  7. .net Core 图片验证码 基于SkiaSharp实现

    public class ImageCaptcha { /// <summary> /// 干扰线的颜色集合 /// </summary> private List<SK ...

  8. react——css样式

    1.行内样式: 两个大括号包着.第一个大括号表示里面写js,第二个大括号里面是样式对象 2.传对象 将对象和结构分离,直接写一个大括号,里面写对象 3.将所有的样式对象合并成一个大对象,直接点 以上样 ...

  9. 如何使用cgdb(一)——窗口切换

    cgdb是一个轻量级的基于控制台的多窗口gdb调试界面.除了标准的gdb控制台之外,cgdb还提供了一个分屏视图,可以在执行的时候显示具备语法高亮的源代码.键盘控制是仿照vim设计的,所以vim用户使 ...

  10. C#读取某一文件夹下的所有文件夹和文件

    static List<string> list = new List<string>();//定义list变量,存放获取到的路径 /// <summary> // ...