tarjan算法详解--图论--强连通图
目录
- 1.有向图连通性(强连通图)
- 1.1有向图
- 1.2有向图连通性
- 2.tarjan算法简述
- 3.实现过程
- 3.1 例题-刻录光盘
- 3.1.1 输入&&初始化
- 3.1.2 tarjan(类似深搜)
- 3.1.3 缩点
- 3.2 完整答案
1.有向图连通性(强连通图)
1.1有向图
如图所示,此图是个有向图。
1.2有向图连通性
也叫强连通图,能从任意一个顶点到达另一个点
注意不一定是双向边!
2.tarjan算法简述
首先,我们要将一个图拆散,看作几个环图
如下图
将此图看作这几部分环图,如下图所示
抽象后如下图所示
这就是 tarjan 最难理解的点 —— 缩点
其他的。。。就很好理解了吧???
下面看我的注释吧
3.实现过程
3.1 例题-刻录光盘
自己去看题[doge]
3.1.1 输入&&初始化
注意 一定要初始化 就因为没初始化我查了半个小时的错
memset(head , -1 , sizeof(head)) ;memset(edge , -1 , sizeof(edge)) ;scanf("%d" , &n) ;for(int i = 1;i <= n;++i){int a ;scanf("%d" , &a) ;while(a != 0){add(i , a) ;scanf("%d" , &a) ;}}
这里我用的 链式前向星 从0开始 初始化-1
链式前向星用法参下
struct Edge{int to ;int next ;
}edge[40005] ;void add(int from , int to){edge[cnt].to = to ;edge[cnt].next = head[from] ;head[from] = cnt++ ;
}
3.1.2 tarjan(类似深搜)
需要进行每个点的遍历
for(int i = 1;i <= n;++i){if(!vis[i]){tarjan(i) ;}}
然后像深搜一样进行搜索
void tarjan(int u){tts++ ;//发现时间增加dfn[u] = low[u] = tts ;//记录发现时间、后代发现时间最小值vis[u] = true ;//标记已访问过instack[u] = true ;//记录已经入栈tj.push(u) ;//入栈for(int i = head[u];i != -1;i = edge[i].next){if(!vis[edge[i].to]){//如果没访问过int v = edge[i].to ;tarjan(v) ;//tarjan算法继续搜low[u] = min(low[v] , low[u]) ;//回溯://如果发现时间比后代的发现时间大,更新后代发现时间最小值}else if(instack[edge[i].to]){low[u]= min(low[u] , dfn[edge[i].to]) ;//如果发现过此节点=,并且还在数据栈中,说明是h图,更新发现时间最小值}}//出环操作if(dfn[u] == low[u]){//如果发现时间 == 后代发现时间count++ ;//新的一个环,环数自增1int v = 0 ;do{//记录此元素颜色并出栈v = tj.top() ;color[v] = count ;tj.pop() ;instack[v] = false ;//记录也要出}while(v != u) ;}
}
3.1.3 缩点
已经讲过,不再赘述
for(int i = 1;i <= n;++i){for(int j = head[i];j != -1;j = edge[j].next){int v = edge[j].to ;if(color[i] != color[v]){din[color[v]]++ ;}}}int ans = 0 ;for(int i = 1;i <= count;++i){if(din[i] == 0){ans++ ;}}printf("%d" , ans) ;
至此完成算法。
3.2 完整答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std ;int head[205] ;
int cnt ;
int low[205] ,dfn[205] ;struct Edge{int to ;int next ;
}edge[40005] ;void add(int from , int to){edge[cnt].to = to ;edge[cnt].next = head[from] ;head[from] = cnt++ ;
}bool vis[205] ;
bool instack[205] ;
stack<int> tj ;
int count = 0 ;
int color[205] ;
int tts = 0 ;void tarjan(int u){tts++ ;//dfn[u] = low[u] = tts ;//vis[u] = true ;instack[u] = true ;tj.push(u) ;for(int i = head[u];i != -1;i = edge[i].next){if(!vis[edge[i].to]){int v = edge[i].to ;tarjan(v) ;low[u] = min(low[v] , low[u]) ;}else if(instack[edge[i].to]){low[u]= min(low[u] , dfn[edge[i].to]) ;}}if(dfn[u] == low[u]){count++ ;int v = 0 ;do{v = tj.top() ;color[v] = count ;tj.pop() ;instack[v] = false ;//}while(v != u) ;}
}int n ;
int din[205] ;int main(){memset(head , -1 , sizeof(head)) ;memset(edge , -1 , sizeof(edge)) ;scanf("%d" , &n) ;for(int i = 1;i <= n;++i){int a ;scanf("%d" , &a) ;while(a != 0){add(i , a) ;scanf("%d" , &a) ;}}for(int i = 1;i <= n;++i){if(!vis[i]){tarjan(i) ;}}for(int i = 1;i <= n;++i){for(int j = head[i];j != -1;j = edge[j].next){int v = edge[j].to ;if(color[i] != color[v]){din[color[v]]++ ;}}}int ans = 0 ;for(int i = 1;i <= count;++i){if(din[i] == 0){ans++ ;}}printf("%d" , ans) ;return 0 ;
}
tarjan算法详解--图论--强连通图相关推荐
- Popular Cows POJ - 2186(tarjan算法)+详解
题意: 每一头牛的愿望就是变成一头最受欢迎的牛.现在有 N头牛,给你M对整数(A,B),表示牛 A认为牛B受欢迎.这种关系是具有传递性的,如果 A认为 B受欢迎, B认为 C受欢迎,那么牛 A也认为牛 ...
- Tarjan 算法详解
一个神奇的算法,求最大连通分量用O(n)的时间复杂度,真实令人不可思议.转自 废话少说,先上题目 题目描述: 给出一个有向图G,求G连通分量的个数和最大连通分量. 输入: n,m,表示G有n个点,m条 ...
- Tarjan算法详解(AcWing 1174 受欢迎的牛)
题目描述: 每一头牛的愿望就是变成一头最受欢迎的牛. 现在有 N 头牛,编号从 1 到 N,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎. 这种关系是具有传递性的,如果 A 认为 B ...
- Tarjan(塔杨)算法详解
Tarjan算法详解 前言 简介 教学代码-有向图的强联通分量 教学代码-点双联通分量 教学代码-边双联通分量 实战代码-边双 实战代码-点双 前言 Tarjan(塔杨)算法其实不是很复杂,对于图这一 ...
- 图论-最短路Dijkstra算法详解超详 有图解
整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...
- 图论2-SAT算法详解
图论2-SAT算法详解 今天我们来介绍一个我个人认为最难的算法,这是为什么呢?肯定会有许多dalao说,不就一个2-SAT,我两分钟就A掉了.然而2-SAT的细节非常的多,稍不注意就会写错,而且测试困 ...
- Union-Find 并查集算法详解
Union-Find 并查集算法详解 文章目录 Union-Find 并查集算法详解 一.问题介绍 二.基本思路 三.平衡性优化 四.路径压缩 五.总结 六.例题 一.问题介绍 简单说,动态连通性其实 ...
- 谱聚类算法详解及代码实现
谱聚类算法详解及代码实现 文章目录 谱聚类算法详解及代码实现 参考 关于谱聚类介绍 谱聚类概述 谱聚类前置知识 无向权重图 邻接矩阵 度矩阵 拉普拉斯矩阵 相似度矩阵 确定目标函数 初始化目标函数(最 ...
- Matlab人脸检测算法详解
这是一个Matlab人脸检测算法详解 前言 人脸检测结果 算法详解 源代码解析 所调用函数解析 bwlabel(BW,n) regionprops rectangle 总结 前言 目前主流的人脸检测与 ...
最新文章
- linuxSVN版本库及同步文件到WEB目录
- sscanf高级用法级正则表达式
- 来个邪恶假说,假如有人把支付宝所有存储服务器炸了,我们在里边的钱是不是都丢了?
- sizeof和strlen()区别
- 动态规划(一)入门例子
- JavaFX中的塔防(6)
- DjangoORM字段介绍
- 20135302魏静静——linux课程第三周实验及总结
- AtomicStampedReference解决CAS的ABA问题
- Android源码学习(一)系统源码初识
- 超市库存java管理系统_Java案例:超市库存管理系统
- hive相关的example
- Siebel应用数据结构层次
- 使用javaSwing搭建一个简单的聊天室
- python做平面设计-Python系列干货之——Python与设计模式
- Fork/Join(分开/联合)
- 司科水果o2o_水果o2o系统_生鲜配送水果o2o系统开发
- 解决 input 输入框在 iOS 系统中无法输入内容
- 使用Python调用Nessus 接口实现自动化扫描
- PaadleInference源码编译操作流程
热门文章
- 做双线策略路由用的网通ip段
- 常用的IDEA 与 eclipse快捷键
- 前端压缩图片 -- vue项目使用localResizeIMG插件 -- 实例
- python冒泡排序算法非递归_python 冒泡排序,递归
- 中通停牌核查,再次收紧jg力度?
- oracle 左连接
- [编程题]手机屏幕解锁模式vivo笔试题
- 阿里云版rocketmq报异常: No route info of this topic解决方案
- python生成exe,pyinstaller编码错误或闪退,果断换坑cxfreeze!
- JTA Transactions