【原创】tarjan算法初步(强连通子图缩点)
【原创】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算法初步(强连通子图缩点)的更多相关文章
- Tarjan算法分解强连通分量(附详细参考文章)
Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...
- tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)
这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...
- Tarjan算法初步
一.前置知识: 强连通分量:有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(stron ...
- Tarjan在图论中的应用(一)——用Tarjan来实现强连通分量缩点
前言 \(Tarjan\)是一个著名的将强连通分量缩点的算法. 大致思路 它的大致思路就是在图上每个联通块中任意选一个点开始进行\(Tarjan\)操作(依据:强连通分量中的点可以两两到达,因此从任意 ...
- [学习笔记] Tarjan算法求强连通分量
今天,我们要探讨的就是--Tarjan算法. Tarjan算法的主要作用便是求一张无向图中的强连通分量,并且用它缩点,把原本一个杂乱无章的有向图转化为一张DAG(有向无环图),以便解决之后的问题. 首 ...
- HDU 1269 迷宫城堡 tarjan算法求强连通分量
基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...
- Tarjan算法【强连通分量】
转自:byvoid:有向图强连通分量的Tarjan算法 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断 ...
- Tarjan 算法求 LCA / Tarjan 算法求强连通分量
[时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarj ...
- 【算法】Tarjan算法求强连通分量
概念: 在有向图G中,如果两个定点u可以到达v,并且v也可以到达u,那么我们称这两个定点强连通. 如果有向图G的任意两个顶点都是强连通的,那么我们称G是一个强连通图. 一个有向图中的最大强连通子图,称 ...
随机推荐
- Thinking In Java 4th Chap3 操作符
若String后接一‘+’运算符,其后元素自动转化为String类型 注意:若对对象赋值另一对象,操作对应的是引用,如c=d,则c和d都指向原来d指向的对象 生成随机数:Random rand=new ...
- AC自动机fail树上dfs序建线段树+动态memset清空
题意:http://acm.hdu.edu.cn/showproblem.php?pid=4117 思路:https://blog.csdn.net/u013306830/article/detail ...
- 在windows系统下打包linux平台运行的go程序
在windows系统下打包linux平台运行的go程序 1.先在main.go下打包成.exe可执行程序测试代码是否正确 //cd到main.go目录 go build //打包命令 如果打包成功则表 ...
- nginx 实践配置
nginx.conf文件 user root; worker_processes 1; error_log logs/error.log crit; #error_log logs/error.log ...
- MyBatis 源码篇-Transaction
本章简单介绍一下 MyBatis 的事务模块,这块内容比较简单,主要为后面介绍 mybatis-spring-1.**.jar(MyBatis 与 Spring 集成)中的事务模块做准备. 类图结构 ...
- 作业13:Map相关知识点(一)
一 Map相关类图 二 Map接口 1 Map接口中的方法 jdk 方法名 简单描述 put(K,V):V 添加value,当Key对应无值,返回null;有值则返回上一个值.(覆盖式,可以反复覆盖前 ...
- 使用X.509数字证书加密解密实务(二)-- 使用RSA证书加密敏感数据
一. 使用RSA证书加.解密敏感数据 X.509证书标准支持三种不对称加密算法:RSA, DSA, Diffie-Hellman algorithms.最常用的是RSA算法.所以本文就以前面章节使用 ...
- JS基础_函数的参数
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- ES6入门:数据劫持、Proxy、Reflect
什么是数据劫持 Object数据劫持实现原理 Array数据劫持的实现原理 Proxy.Reflect 一.什么是数据劫持 定义:访问或者修改对象的某个属性时,在访问和修改属性值时,除了执行基本的数据 ...
- 安卓SharedPreferences类的使用
package com.lidaochen.phonecall; import android.content.Intent; import android.content.SharedPrefere ...