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. hdu-5497 Inversion(滑动窗口+树状数组)

    题目链接: Inversion Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  2. EDM总结

    1.  使用table 布局,align="center" 2.  尽量不要用padding-left ,padding-right 样式: 3.  CSS的浮动定位: 4.  不 ...

  3. HDU 5044 Tree --树链剖分

    题意:给一棵树,两种操作: ADD1: 给u-v路径上所有点加上值k, ADD2:给u-v路径上所有边加上k,初始值都为0,问最后每个点和每条边的值,输出. 解法:树链剖分可做,剖出来如果直接用线段树 ...

  4. TestLink学习一:Windows搭建Apache+MySQL+PHP环境

    PHP集成开发环境有很多,如XAMPP.AppServ......只要一键安装就把PHP环境给搭建好了.但这种安装方式不够灵活,软件的自由组合不方便,同时也不利于学习.所以我还是喜欢手工搭建PHP开发 ...

  5. app:transformClassesWithJarMergingForDebug uplicate entry: android/support/v4/app/BackStackState$1.class

    .Execution failed for task ':app:transformClassesWithJarMergingForDebug'.> com.android.build.api. ...

  6. 经典71道Android试题及答案

    本文为开发者奉献了70道经典Android面试题加答案--重要知识点几乎都涉及到了,你还等啥,赶紧收藏吧!! 1. 下列哪些语句关于内存回收的说明是正确的? (b) A. 程序员必须创建一个线程来释放 ...

  7. javascript单元测试工具

    单元测试关注的是验证一个模块或一段代码的执行效果是否和设计或预期一样.有些开发人员认为,编写测试用例浪费时间而宁愿去编写新的模块.然而,在处理大型应用程序时,单元测试实际上会节省时间:它能帮助您跟踪问 ...

  8. mysqli事务处理demo

    <?php  $mysqli=new mysqli("localhost", "root", "123456", "xsph ...

  9. 页的lock

    文件为什么要加锁? 页的操作为什么要加锁? http://linux.chinaunix.net/techdoc/system/2007/06/11/959844.shtml 上面一个页面有简单介绍什 ...

  10. 推荐一款开源的C#TCP通讯框架

    原来收费的TCP通讯框架开源了,这是一款国外的开源TCP通信框架,使用了一段时间,感觉不错,介绍给大家 框架名称是networkcomms 作者开发了5年多,目前已经停止开发,对于中小型的应用场景,够 ...