目录

  • 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算法详解--图论--强连通图相关推荐

  1. Popular Cows POJ - 2186(tarjan算法)+详解

    题意: 每一头牛的愿望就是变成一头最受欢迎的牛.现在有 N头牛,给你M对整数(A,B),表示牛 A认为牛B受欢迎.这种关系是具有传递性的,如果 A认为 B受欢迎, B认为 C受欢迎,那么牛 A也认为牛 ...

  2. Tarjan 算法详解

    一个神奇的算法,求最大连通分量用O(n)的时间复杂度,真实令人不可思议.转自 废话少说,先上题目 题目描述: 给出一个有向图G,求G连通分量的个数和最大连通分量. 输入: n,m,表示G有n个点,m条 ...

  3. Tarjan算法详解(AcWing 1174 受欢迎的牛)

    题目描述: 每一头牛的愿望就是变成一头最受欢迎的牛. 现在有 N 头牛,编号从 1 到 N,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎. 这种关系是具有传递性的,如果 A 认为 B ...

  4. Tarjan(塔杨)算法详解

    Tarjan算法详解 前言 简介 教学代码-有向图的强联通分量 教学代码-点双联通分量 教学代码-边双联通分量 实战代码-边双 实战代码-点双 前言 Tarjan(塔杨)算法其实不是很复杂,对于图这一 ...

  5. 图论-最短路Dijkstra算法详解超详 有图解

    整体来看dij就是从起点开始扩散致整个图的过程,为什么说他稳定呢,是因为他每次迭代,都能得到至少一个结点的最短路.(不像SPFA,玄学复杂度) 但是他的缺点就是不能处理带负权值的边,和代码量稍稍复杂. ...

  6. 图论2-SAT算法详解

    图论2-SAT算法详解 今天我们来介绍一个我个人认为最难的算法,这是为什么呢?肯定会有许多dalao说,不就一个2-SAT,我两分钟就A掉了.然而2-SAT的细节非常的多,稍不注意就会写错,而且测试困 ...

  7. Union-Find 并查集算法详解

    Union-Find 并查集算法详解 文章目录 Union-Find 并查集算法详解 一.问题介绍 二.基本思路 三.平衡性优化 四.路径压缩 五.总结 六.例题 一.问题介绍 简单说,动态连通性其实 ...

  8. 谱聚类算法详解及代码实现

    谱聚类算法详解及代码实现 文章目录 谱聚类算法详解及代码实现 参考 关于谱聚类介绍 谱聚类概述 谱聚类前置知识 无向权重图 邻接矩阵 度矩阵 拉普拉斯矩阵 相似度矩阵 确定目标函数 初始化目标函数(最 ...

  9. Matlab人脸检测算法详解

    这是一个Matlab人脸检测算法详解 前言 人脸检测结果 算法详解 源代码解析 所调用函数解析 bwlabel(BW,n) regionprops rectangle 总结 前言 目前主流的人脸检测与 ...

最新文章

  1. linuxSVN版本库及同步文件到WEB目录
  2. sscanf高级用法级正则表达式
  3. 来个邪恶假说,假如有人把支付宝所有存储服务器炸了,我们在里边的钱是不是都丢了?
  4. sizeof和strlen()区别
  5. 动态规划(一)入门例子
  6. JavaFX中的塔防(6)
  7. DjangoORM字段介绍
  8. 20135302魏静静——linux课程第三周实验及总结
  9. AtomicStampedReference解决CAS的ABA问题
  10. Android源码学习(一)系统源码初识
  11. 超市库存java管理系统_Java案例:超市库存管理系统
  12. hive相关的example
  13. Siebel应用数据结构层次
  14. 使用javaSwing搭建一个简单的聊天室
  15. python做平面设计-Python系列干货之——Python与设计模式
  16. Fork/Join(分开/联合)
  17. 司科水果o2o_水果o2o系统_生鲜配送水果o2o系统开发
  18. 解决 input 输入框在 iOS 系统中无法输入内容
  19. 使用Python调用Nessus 接口实现自动化扫描
  20. PaadleInference源码编译操作流程

热门文章

  1. 做双线策略路由用的网通ip段
  2. 常用的IDEA 与 eclipse快捷键
  3. 前端压缩图片 -- vue项目使用localResizeIMG插件 -- 实例
  4. python冒泡排序算法非递归_python 冒泡排序,递归
  5. 中通停牌核查,再次收紧jg力度?
  6. oracle 左连接
  7. [编程题]手机屏幕解锁模式vivo笔试题
  8. 阿里云版rocketmq报异常: No route info of this topic解决方案
  9. python生成exe,pyinstaller编码错误或闪退,果断换坑cxfreeze!
  10. JTA Transactions