SCC即强连通分量,即一个图的子图,其中的点能相互到达,全称是strongly connected component。

Tarjan算法是用来找出图的SCC。

伪代码

int index = ;  //全局变量i
stack s; //全局堆栈s
void tarjan(vertex v){
LOW[v] = DFN[v] = ++index; //初始化LOW和DFN
s.push(v);
for(所有与v相连的节点w){
if(w没有被访问过){
//(v, w)是搜索树上的边
tarjan(w);
LOW[v] = min(LOW[v], LOW[w]);
}
else if(DFN[w] < DFN[v]){
//(v, w)是交叉边或后向边,判断剔除了无用的前向边
if(w in s)
LOW[v] = min(LOW[v], DFN[w])
}
}
if(DFN[v] == LOW[v]){
while(s.top() >= v){
//移除栈内元素直到v,构成一个强连通分量
//
s.pop();
}
}
}

  

实际上LOW[v] = min(LOW[v], DFN[w])这句可以写成LOW[v] = min(LOW[v], LOW[w]),只要保证LOW[v]比DFN[v]小就可以。

题目

POJ 2186 Popular Cows

找出受所有人欢迎的奶牛,用tarjan缩点,缩点后的图里如果只有一个出度为0,那就把该缩点包含的点的个数输出,否则输出0。

#include <cstdio>
#include <cstring>
#include <stack>
#include<vector>
using namespace std;
const int N = ;
const int M = ;
struct data
{
int to,next;
} tu[M];
int head[N],ip;
int dfn[N],low[N];//dfn[]表示深搜的步数,low[u]表示u或u的子树能够追溯到的最早的栈中节点的次序号
int sccno[N];//缩点数组,表示某个点对应的缩点值
int cnt[N];//这个缩点有几个点组成
int step;
int scc_cnt;//强连通分量个数
int o[N];
int n,m,num,ans;
void init()
{
memset(head,-,sizeof head);
scanf("%d%d",&n,&m);
for(int i=; i<=m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
tu[ip].to=v,tu[ip].next=head[u],head[u]=ip++;
}
}
stack<int> S;
void dfs(int u)
{
dfn[u]=low[u]=++step;
S.push(u);
for(int i=head[u]; i!=-; i=tu[i].next)
{
int v=tu[i].to;
if(!dfn[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!sccno[v])
low[u]=min(low[u],low[v]);
}
if(low[u]==dfn[u])
{
scc_cnt++;
while()
{
int x=S.top();
S.pop();
sccno[x]=scc_cnt;
cnt[scc_cnt]++;
if(x==u)break;
}
}
}
void solve()
{
for(int u=; u<=n; u++)
for(int i=head[u]; i!=-; i=tu[i].next)
{
int v=tu[i].to;
if(sccno[u]!=sccno[v]){
o[sccno[u]]++;
break;
}
}
for(int i=; i<=scc_cnt; i++)
if(o[i]==)
{
ans=i;
num++;
if(num>)break;
}
if(num==)
ans= cnt[ans];
else ans=;
}
int main()
{
//freopen("in.txt","r",stdin);
init();
for(int i=; i<=n; i++)
if(!dfn[i])dfs(i);
solve();
printf("%d\n",ans);
return ;
}

  

Tarjan算法的更多相关文章

  1. 有向图强连通分量的Tarjan算法

    有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...

  2. 点/边 双连通分量---Tarjan算法

    运用Tarjan算法,求解图的点/边双连通分量. 1.点双连通分量[块] 割点可以存在多个块中,每个块包含当前节点u,分量以边的形式输出比较有意义. typedef struct{ //栈结点结构 保 ...

  3. 割点和桥---Tarjan算法

    使用Tarjan算法求解图的割点和桥. 1.割点 主要的算法结构就是DFS,一个点是割点,当且仅当以下两种情况:         (1)该节点是根节点,且有两棵以上的子树;         (2)该节 ...

  4. Tarjan算法---强联通分量

    1.基础知识 在有向图G,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子 ...

  5. (转载)LCA问题的Tarjan算法

    转载自:Click Here LCA问题(Lowest Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两 ...

  6. 强连通分量的Tarjan算法

    资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...

  7. [知识点]Tarjan算法

    // 此博文为迁移而来,写于2015年4月14日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vxnx.html UPD ...

  8. Tarjan 算法&模板

    Tarjan 算法 一.算法简介 Tarjan 算法一种由Robert Tarjan提出的求解有向图强连通分量的算法,它能做到线性时间的复杂度. 我们定义: 如果两个顶点可以相互通达,则称两个顶点强连 ...

  9. 【小白入门向】tarjan算法+codevs1332上白泽慧音 题解报告

    一.[前言]关于tarjan tarjan算法是由Robert Tarjan提出的求解有向图强连通分量的算法. 那么问题来了找蓝翔!(划掉)什么是强连通分量? 我们定义:如果两个顶点互相连通(即存在A ...

  10. 有向图强连通分量 Tarjan算法

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...

随机推荐

  1. iscroll.js的使用

    入门 Scroll是一个类,每个需要使用滚动功能的区域均要进行初始化.每个页面上的iScroll实例数目在设备的CPU和内存能承受的范围内是没有限制的. 尽可能保持DOM结构的简洁.iScroll使用 ...

  2. 一道题看bitset应用 --ZOJ 3642

    题意:给n个文件,包括文件名和文件大小,然后给出k个关键词,查询包含该关键词的文件的大小总和.文件名为一些中括号括起的关键词的合集. 解法:可用bitset记录每一个关键词在哪些文件中出现,然后查询即 ...

  3. Android SQLite (五 ) 全面详解(三)

    SQLite约束 约束是在表的数据列上强制执行的规则.这些是用来限制可以插入到表中的数据类型.这确保了数据库中数据的准确性和可靠性.约束可以是列级或表级.列级约束仅适用于列,表级约束被应用到整个表. ...

  4. 检查c# 内存泄漏

    c# 内存泄漏检查心得 系统环境 windows 7 x64 检查工具:ANTS Memory Profiler 7 或者 .NET Memory Profiler 4.0 开发的软件为winform ...

  5. Linux 进程通信(共享内存区)

    共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段). 如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映像到自己的私有地址空间中. 如果一个进程更新了段中的数据,其他进程也 ...

  6. C语言 const与指针

    //const与指针 #include<stdio.h> #include<stdlib.h> void main(){ ; ; const int *p; p = & ...

  7. Android nDrawer

    GitHub上一款流行的侧滑,附上自己as编译过的源码http://download.csdn.net/detail/lj419855402/8559039. 留个纪念,说不定以后用得到. 依赖一个l ...

  8. RedHat版的linux安装yum源及redis

    一.前言 最近正在学习redis,但是在安装redis的时候遇到很多坎,在此记录一下. 硬件环境:我用 VMware Workstation Pro 12 安装 Red Hat Enterprise ...

  9. Core Data 使用

    coredata使用了一种完全不同 的方法,你不需要创建类,而是在数据模型编辑器中创建一些实体,然后为这些实体创建托管对象. 实体由属性组成.有三种:特性:关系:提取属性. 使用键值编码来设置属性或检 ...

  10. 报错:'Could not load NIB in bundle: 'NSBundle解决办法

    1.首先检查拼写是否正确: 2.断开连线,重新连接view与files' owner; 3.规避敏感View名.Xcode中有许多名字是系统预留的.你如果用了也会报这个错误.