【原创】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. 网络编程[第三篇]基于tcp协议实现远程连接

    需要用到subprogress模块来远程控制cmd控制台程序来得到控制台的输出信息 一.服务端 —— 控制输出信息 import socket import subprocess #socket实例化 ...

  2. pthread_cancel 相关

    假设线程A对线程B发出了一个取消请求.通过如下函数: #include <pthread.h> int pthread_cancel(pthread_t thread); 参数: thre ...

  3. 利用神器BTrace 追踪线上 Spring Boot应用运行时信息

    概述 生产环境中的服务可能会出现各种问题,但总不能让服务下线来专门排查错误,这时候最好有一些手段来获取程序运行时信息,比如 接口方法参数/返回值.外部调用情况 以及 函数执行时间等信息以便定位问题.传 ...

  4. MySQL 聚合函数(一)聚合(组合)函数概述

    MySQL版本:5.7+ 本节介绍对值的集合进行操作的组合(聚合)函数.翻译自:Aggregate (GROUP BY) Function Descriptions 一.MySQL 5.7中的聚合函数 ...

  5. hdu 1506 最大子矩阵面积

    //写动态规划的题目 要把主要问题提炼出来 这里的问题就是求area=(j-k+1)*a[i]  如果找到j k是解决这个题目的关键 这里暴力求肯定是要超时的 这里用dp来优化 #include< ...

  6. Windows编程 Windows程序的生与死(下)

    再谈程序之“死” 记得在第二回中我对程序的“死”只是一句话带过,因为我还没有铺垫好,好了现在我们可以详细的分析一下这个过程了. 这还要从while消息循环说起,还记得GetMessage函数吗?它是一 ...

  7. 在QT中添加LIB的方法

    注意:-L后面跟着的目录不能用空格,否则会出现读不到的情况. 例如win32下添加D:\app\my.lib   就 pro文件中 LIBS += -LD:\app\debug\ -lmy

  8. idea控制台乱码修改

    我的idea当前版本是2019.2.2 试了很多,只有这个有效果 工具类→HELP→Edit Custom VM OPtions中加 -Dfile.encoding=utf-8 然后重启IDEA 这个 ...

  9. 解释mysql 语句

    一.在我们创建mysql数据库的时候我们经常会用到这句SQL: CREATE DATABASE TEST DEFAULT CHARACTER SET utf8 COLLATE utf8_general ...

  10. C# 一个数组集合,任意组合,不遗漏,不重复

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using S ...