求图的强连通分量--tarjan算法
一:tarjan算法详解
for each (u, v) in E {
if (v is not visted) {
tarjan(v)
low[u] = min(low[u], low[v])
}
else if (v in stack) {
low[u] = min(low[u], dfn[v]) /*这里是low[u] = min(low[u], low[v])也是可以的,因为如果这个点被访问了,而且仍然待在栈中,说明u---v是一条回边,那么这里用dfn[v]
low[v]都是相同了的*/
}
} if (dfn[u] == low[u])
{ //u是一个强连通分量的根 repeat v = stack.pop
print v
until (u== v) } //退栈,把整个强连通分量都弹出来 } //复杂度是O(E+V)的
例题:1001. [WZOI2011 S3] 消息传递(来源sojs.tk)
★★ 输入文件:messagew.in 输出文件:messagew.out 简单对比
时间限制:1 s 内存限制:128 MB
- Problem 2 消息传递 (messagew.pas/c/cpp)
- 问题描述
- WZland开办了一个俱乐部(这里面可以干任何的事情),这引来了许多的人来加入。俱乐部的人数越来越多,关系也越来越复杂……
- 俱乐部的人来自各个地方,为了增加友谊,俱乐部举行了一次晚会。晚会上又进行了一个传话游戏,如果A认识B,那么A收到某个消息,就会把这个消息传给B,以及所有A认识的人(如果A认识B,B不一定认识A),所有人从1到N编号。
- 现在给出所有“认识”关系,俱乐部的负责人WZland的国王想知道一个十分简单的问题:如果A发布一条新消息,那么会不会经过若干次传话后,这个消息传回给了A,1≤A≤N。但是WZland的国王是出了名的数学差,幸好的是你在他的身边,于是他就将这个问题交给你来解决。
- 输入格式
- 输入数据中的第一行是两个数N和M,两数之间有一个空格,表示人数和认识关系数。
- 接下来的M行,每行两个数A和B,表示A认识B(1A, BN,AB)。
- 输出格式
- 输出文件中一共有N行,每行一个字符“T”或“F”。第i行如果是“T”,表示i发出一条新消息会传回给i;如果是“F”,表示i发出一条新消息不会传回给i。
- 样例输入输出
- message.in
- 4 6
- 1 2
- 2 3
- 4 1
- 3 1
- 1 3
- 2 3
- message.out
- T
- T
- T
- F
- 数据规模
- 对于30%的数据,N≤1000,M≤20000;
- 对于50%的数据,N≤10000,M≤100000;
- 对于100%的数据,N≤100000,M≤200000;
- 认识关系可能会重复给出。
- 时间限制
- 1s
- 解析:”认识关系可能会重复给出。“根本不用处理,不会影响答案的。
- 代码及其分析:
#include<iostream>
using namespace std;
#include<cstdio>
#define N 100100
#include<vector>
vector<int>G[N];
vector<int>ans[N];
int clac=;
bool inzhan[N];
#include<stack>
#include<cstring>
stack<int>s;
int low[N],dfn[N];
bool flag[N]={},ok[N]={};
int n,m;
int Index;
void input()
{
Index=;
scanf("%d%d",&n,&m);
int a,b;
for(int i=;i<=m;++i)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
}
memset(inzhan,false,sizeof(inzhan));
memset(dfn,-,sizeof(dfn));
memset(low,-,sizeof(low));
}
void Tarjan(int k)
{
int j;
dfn[k]=low[k]=++Index;/*tarjan过程,记录到达该点的时间,和从该点出发能到达的时间最小的点*/
inzhan[k]=true;/*入栈*/
s.push(k);
for(int i=;i<G[k].size();++i)
{
int tp=G[k][i];/*邻接表储存,G[k][i]表示从k点出发的第i条边的终点编号*/
if(low[tp]==-)
{
Tarjan(tp);
low[k]=min(low[k],low[tp]);
}
else if(inzhan[tp])
low[k]=min(low[tp],low[k]);
/*整理总共有三种情况:未被访问,访问了但是是不是强连通分量还不知道(也就是仍在栈中),访问了已经出栈了(这种不用处理,因为如果这个点在好几个强连通分量中,那么他此时一定没有出栈。因为深搜嘛)*/
}
if(low[k]==dfn[k])/*low[k]==dfn[k]是这个强连通分量的标志,也就是起始位置,不能再向上找了*/
{
int l;
clac++;/*强连通分量个数*/
do{
l=s.top();
s.pop();
ans[clac].push_back(l);
inzhan[l]=false;
}while(l!=k);
if(ans[clac].size()>)
flag[clac]=true;/*记录这个强连通分量中的所有点是可以传话成功的,下面在重标记每一个点*/
}
}
void OUT()
{
for(int i=;i<=clac;++i)
if(flag[i])
{
for(int j=;j<ans[i].size();++j)
ok[ans[i][j]]=true;
}
for(int i=;i<=n;++i)
if(ok[i])
printf("T\n");
else printf("F\n");
}
int main()
{
freopen("messagew.in","r",stdin);
freopen("messagew.out","w",stdout);
input();
for(int i=;i<=n;++i)
if(dfn[i]==-)
Tarjan(i);
OUT();
fclose(stdin);
fclose(stdout);
return ;
}
求图的强连通分量--tarjan算法的更多相关文章
- 有向图强连通分量 Tarjan算法
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...
- 有向图强连通分量Tarjan算法
在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...
- 图之强连通、强连通图、强连通分量 Tarjan算法
原文地址:https://blog.csdn.net/qq_16234613/article/details/77431043 一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶 ...
- 图的连通性:有向图强连通分量-Tarjan算法
参考资料:http://blog.csdn.net/lezg_bkbj/article/details/11538359 上面的资料,把强连通讲的很好很清楚,值得学习. 在一个有向图G中,若两顶点间至 ...
- 图论-强连通分量-Tarjan算法
有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在 ...
- POJ1236_A - Network of Schools _强连通分量::Tarjan算法
Time Limit: 1000MS Memory Limit: 10000K Description A number of schools are connected to a compute ...
- [有向图的强连通分量][Tarjan算法]
https://www.byvoid.com/blog/scc-tarjan 主要思想 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的 ...
- 萌新学习图的强连通(Tarjan算法)笔记
--主要摘自北京大学暑期课<ACM/ICPC竞赛训练> 在有向图G中,如果任意两个不同顶点相互可达,则称该有向图是强连通的: 有向图G的极大强连通子图称为G的强连通分支: Tarjan算法 ...
- 强连通分量——tarjan算法
概念: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通.如果有向图G的每两个顶点都强连 ...
随机推荐
- peewee外键性能问题
# 转载自:https://www.cnblogs.com/miaojiyao/articles/5217757.html 下面讨论一下用peewee的些许提高性能的方法. 避免N+1查询 N+1查询 ...
- linux系统下git使用
转载:http://www.cnblogs.com/bear2flymoon/p/4335364.html?ADUIN=563508762&ADSESSION=1430887070&A ...
- C#文件路径乱码
最近学C#,用C#写serialport遇到了一点小问题记录一下. 问题一: if (!string.IsNullOrEmpty(filePath.ToString())) { try { fs = ...
- Redis、mongdb、memcached的个人总结
有测试的实例:http://colbybobo.iteye.com/blog/1986786 详细描述优缺点:https://www.cnblogs.com/binyue/p/4582550.html
- MySQL的读写分离---主从复制、主主复制
1.复制是基于BinLog日志 存在三种日志格式:Statement:存储Sql语句,存储日志量是最小的.有可能复制不一致Row:存储event数据,存储日志量大,但是不能很直接进行读取:Mixed: ...
- Populating Next Right Pointers in Each Node I&&II ——II仍然需要认真看看
Populating Next Right Pointers in Each Node I Given a binary tree struct TreeLinkNode { TreeLinkNode ...
- SQL Server 用链接服务器 同步SqlServer与MySQL
=======================================================================================SQL SERVER链接S ...
- SnagIt截图后无法在编辑器打开,不显示截图内容的解决办法(转)
方法1: 用SnagIt截图后,弹出的编辑器里不显示刚才截图的内容,解决办法如下: 完全退出Snagit和编辑器,删除以下文件夹: Win7用户 C:\Users\Administrator\AppD ...
- 事务管理配置与@Transactional注解使用
spring,mybatis事务管理配置与@Transactional注解使用 概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framewor ...
- AC日记——[HNOI2008]GT考试 bzoj 1009
1009 思路: KMP上走DP(矩阵加速): DP[i][j]表示当前在第i位,同是匹配到不吉利串的第j位的方案数: 代码: #include <bits/stdc++.h> using ...