强连通分量(Tarjan)
//P2002解题思路:
//先求SCC,缩点后,转换为DAG(有向无环图)
//在DAG上统计入度为0的scc数量即可
//Tarjan时间复杂度:O(N+E),每个点和每条边刚好被访问一次,在空间和时间上比Kosaraju好一些。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=500010;
struct edge{ int t; edge *nxt; edge(int to, edge * next){ t=to, nxt=next; } };
edge * h[maxn]; //h2是反图
void add(int u, int v){ h[u]=new edge(v, h[u]); }
int n, m, v[maxn], st[maxn], st_k, dfn[maxn], low[maxn], timestamp, sccno[maxn], scc_cnt, scc_indegree[maxn];
void tarjan(int x)
{
dfn[x]=low[x]=++timestamp;
st[++st_k]=x, v[x]=1; //v数组记录x是否在堆栈中
for(edge *p=h[x]; p; p=p->nxt)
{
if(!dfn[p->t]) tarjan(p->t), low[x]=min(low[x], low[p->t]); //通过dfn值判断点是否访问过
else if(v[p->t]) low[x]=min(low[x], low[p->t]); //通过v值判断该点是否在堆栈中
}
if(dfn[x]==low[x]) //发现SCC
{
sccno[x]=++scc_cnt; //scc计数,同时标记x
while(st[st_k]!=x)
{
sccno[st[st_k]]=scc_cnt;
v[st[st_k]]=0;
st_k--;
}
v[st[st_k--]]=0; //取消x在堆栈中的标记
}
}
int main()
{
scanf("%d%d", &n, &m);
for(int i=1, b, e; i<=m; i++)
{
scanf("%d%d", &b, &e);
if(b!=e) add(b, e); //去除自环
}
for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i);
for(int i=1; i<=n; i++) //统计每个scc的入度
for(edge *p=h[i]; p; p=p->nxt)
if(sccno[i]!=sccno[p->t]) scc_indegree[sccno[p->t]]++; //起点和终点不在一个scc中才统计入度
int ans=0;
for(int i=1; i<=scc_cnt; i++) if(!scc_indegree[i]) ans++; //统计入度为0的scc的个数
printf("%d\n", ans);
return 0;
}
强连通分量(Tarjan)的更多相关文章
- 强连通分量(tarjan求强连通分量)
双DFS方法就是正dfs扫一遍,然后将边反向dfs扫一遍.<挑战程序设计>上有说明. 双dfs代码: #include <iostream> #include <cstd ...
- 有向图强连通分量 Tarjan算法
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...
- POJ2186 Popular Cows 强连通分量tarjan
做这题主要是为了学习一下tarjan的强连通分量,因为包括桥,双连通分量,强连通分量很多的求法其实都可以源于tarjan的这种方法,通过一个low,pre数组求出来. 题意:给你许多的A->B ...
- [有向图的强连通分量][Tarjan算法]
https://www.byvoid.com/blog/scc-tarjan 主要思想 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的 ...
- 图的连通性:有向图强连通分量-Tarjan算法
参考资料:http://blog.csdn.net/lezg_bkbj/article/details/11538359 上面的资料,把强连通讲的很好很清楚,值得学习. 在一个有向图G中,若两顶点间至 ...
- 强连通分量tarjan缩点——POJ2186 Popular Cows
这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定 ...
- 图之强连通、强连通图、强连通分量 Tarjan算法
原文地址:https://blog.csdn.net/qq_16234613/article/details/77431043 一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶 ...
- 图论-强连通分量-Tarjan算法
有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在 ...
- 求图的强连通分量--tarjan算法
一:tarjan算法详解 ◦思想: ◦ ◦做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间 ...
- POJ1236_A - Network of Schools _强连通分量::Tarjan算法
Time Limit: 1000MS Memory Limit: 10000K Description A number of schools are connected to a compute ...
随机推荐
- Jmeter分布式部署
当单机没有足够能力来模拟较重的负载,可以使用jmeter分布式测试功能, 通过一个Jmeter控制台来远程控制多个Jmeter引擎完成测试. 每个线程均独立运行测试计划.因此,线程组常用来模拟并发用户 ...
- C语言货架02
第1章 程序设计和C语言 最简单的C语言程序举例 #include<stdio.h> int main() { printf("这是一个C程序\n"); : } C语 ...
- Go语言打造以太坊智能合约测试框架(level3)
传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...
- Powershell-获取MAC地址对应IP信息
因业务需要在DHCP服务器上绑定设备MAC,提示"指定的IP地址或硬件地址正被其他客户端使用",与业务同事沟通之前该设备做过地址保留,具体对应地址遗忘了. 问题描述: a.按照用户 ...
- 从输出日志中提取接口的入参和返回做为用例导入到excel中
1 背景 接口用例已经在项目中的yml文件中编写,但是yml文件不能做为交付文档用,本文对工作中从接口输出日志中提取用例信息,并导入到excel文件中做了总些 2 工具 idea,notepad+ ...
- CMake与Make最简单直接的区别 [转]
写程序大体步骤为: 1.用编辑器编写源代码,如.c文件. 2.用编译器编译代码生成目标文件,如.o. 3.用链接器连接目标代码生成可执行文件,如.exe. 但如果源文件太多,一个一个编译时就会特别麻烦 ...
- C# 中如何判断字符串的相似度
基于 F23.StringSimilarity.dll 组件.Github 上可以搜索到该组件. 核心方法: var l = new Levenshtein(); double tempValue ...
- dig请求和回应中的参数解释
; <<>> DiG 9.9.5-3ubuntu0.6-Ubuntu <<>> baidu.com dig这个程序的版本号和要查询的域名 ;; glob ...
- jmeter(二十六)生成HTML性能测试报告
性能测试工具Jmeter由于其体积小.使用方便.学习成本低等原因,在现在的性能测试过程中,使用率越来越高,但其本身也有一定的缺点,比如提供的测试结果可视化做的很一般. 不过从3.0版本开始,jmete ...
- .NET、PHP、MySql、JS中的时间戳你每次是手写还是复制?这篇文章让你一次性搞懂
什么是时间戳(chuō)? 答:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数. 为什么时间戳要从1970年01月0 ...