poj1236 Tarjan算法模板 详解
思想:
做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间。初始时dfn[i]=low[i]
在DFS过程中会形成一搜索树。在搜索树上越先遍历到的节点,显然dfn的值就越小。
DFS过程中,碰到哪个节点,就将哪个节点入栈。栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈。
如果发现某节点u有边连到搜索树中栈里的节点v,则更新u的low 值为dfn[v](更新为low[v]也可以)。
如果一个节点u已经DFS访问结束,而且此时其low值等于dfn值,则说明u可达的所有节点,都不能到达任何在u之前被DFS访问的节点
---- 那么该节点u就是一个强连通分量在DFS搜索树中的根。
此时将栈中所有节点弹出,包括u,就找到了一个强连通分量
以poj 1236 Network of Schools 为例说明
192K
0MS
#include <string.h>
#include <stdio.h>
#define V
105
#define E
100500
struct edge
{
int to,
next;
}Edge[E];
int head[V], e, n;
int indeg[V], outdeg[V]; //点的入度和出度数
int belong[V], low[V], dfn[V], scc, cnt;//dfn[]:遍历到u点的时间;
low[]:u点可到达的各点中最小的dfn[v]
int S[V], top;
bool vis[V];//v是否在栈中
int addedge(int u, int v)
{
Edge[e].to =
v;
Edge[e].next
= head[u];
head[u] =
e++;
return
0;
}
void tarjan(int u)
{
int v;
dfn[u] =
low[u] = ++cnt;//开始时dfn[u] == low[u]
S[top++] =
u;//不管三七二十一进栈
vis[u] =
true;
for (int
i=head[u]; i!=-1; i=Edge[i].next)
{
v =
Edge[i].to;
if (dfn[v]
== 0)//如果v点还未遍历
{
tarjan(v);//向下遍历
low[u] =
low[u] < low[v] ? low[u] : low[v];//确保low[u]最小
}
else if
(vis[v] && low[u] >
dfn[v])//v在栈中,修改low[u]
low[u] =
dfn[v];
}
if (dfn[u]
== low[u])//u为该强连通分量中遍历所成树的根
{
++scc;
do
{
v =
S[--top];//栈中所有到u的点都属于该强连通分量,退栈
vis[v] =
false;
belong[v] =
scc;
} while (u
!= v);
}
}
int solve()
{
scc = top =
cnt = 0;
memset(dfn,
0, sizeof(dfn));
memset(vis,
false, sizeof(vis));
for (int
u=1; u<=n; ++u)
if (dfn[u]
== 0)
tarjan(u);
return
scc;
}
void count_deg()
{
memset(indeg, 0, sizeof(indeg));
memset(outdeg, 0, sizeof(outdeg));
for (int
u=1; u<=n; ++u)
for (int
i=head[u]; i!=-1; i=Edge[i].next)
{
int v =
Edge[i].to;
if
(belong[u] != belong[v])
{
indeg[belong[v]]++;
outdeg[belong[u]]++;
}
}
}
int main()
{
int u, v,
i;
while
(~scanf("%d", &n))
{
e = 0;
memset(head,
-1, sizeof(head));
for (u=1;
u<=n; ++u)
while
(scanf("%d", &v) &&
v != 0)
addedge(u,
v);
solve();
if (scc ==
1)
printf("1\n0\n");
else
{
count_deg();
int inc = 0,
outc = 0;
for (i=1;
i<=scc; ++i)
{
if (indeg[i]
== 0)
inc++;
if
(outdeg[i] == 0)
outc++;
}
printf("%d\n%d\n", inc, (inc > outc ? inc :
outc));
}
}
return
0;
}
poj1236 Tarjan算法模板 详解的更多相关文章
- Floyd算法模板--详解
对于无权的图来说: 若从一顶点到另一顶点存在着一条路径,则称该路径长度为该路径上所经过的边的数目,它等于该路径上的顶点数减1. 由于从一顶点到另一顶点可能存在着多条路径,每条路径上所经过的边数可能不同 ...
- 一致性算法RAFT详解
原帖地址:http://www.solinx.co/archives/415?utm_source=tuicool&utm_medium=referral一致性算法Raft详解背景 熟悉或了解 ...
- 各大公司广泛使用的在线学习算法FTRL详解
各大公司广泛使用的在线学习算法FTRL详解 现在做在线学习和CTR常常会用到逻辑回归( Logistic Regression),而传统的批量(batch)算法无法有效地处理超大规模的数据集和在线数据 ...
- C++模板详解
参考:C++ 模板详解(一) 模板:对类型进行参数化的工具:通常有两种形式: 函数模板:仅参数类型不同: 类模板: 仅数据成员和成员函数类型不同. 目的:让程序员编写与类型无关的代码. 注意:模板 ...
- 转】Mahout推荐算法API详解
原博文出自于: http://blog.fens.me/mahout-recommendation-api/ 感谢! Posted: Oct 21, 2013 Tags: itemCFknnMahou ...
- MD5算法步骤详解
转自MD5算法步骤详解 之前要写一个MD5程序,但是从网络上看到的资料基本上一样,只是讲了一个大概.经过我自己的实践,我决定写一个心得,给需要实现MD5,但又不要求很高深的编程知识的童鞋参考.不多说了 ...
- 25.C++- 泛型编程之函数模板(详解)
本章学习: 1)初探函数模板 2)深入理解函数模板 3)多参函数模板 4)重载函数和函数模板 当我们想写个Swap()交换函数时,通常这样写: void Swap(int& a, int&am ...
- 26.C++- 泛型编程之类模板(详解)
在上章25.C++- 泛型编程之函数模板(详解) 学习了后,本章继续来学习类模板 类模板介绍 和函数模板一样,将泛型思想应用于类. 编译器对类模板处理方式和函数模板相同,都是进行2次编译 类模板通 ...
- [转]Mahout推荐算法API详解
Mahout推荐算法API详解 Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeepe ...
随机推荐
- Kail安装后的配置
安装完Kail系统后进行简单的几项配置可以让使用更方便 VMware安装Kail系统这里就不介绍了,大家可以参考这个博客:http://www.cnblogs.com/xuanhun/p/568831 ...
- 进度条插件使用demo
1.下载地址: http://down.htmleaf.com/1502/201502031710.zip 2.效果图: 3.HTML代码:其中80设置当前所占百分比,即蓝色部分比例:注意引入必须的j ...
- 洛谷 P1784 数独
题目描述 数独是根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字均含1-9,不重复.每一道合格的数独谜题都有且仅有唯一答案,推理方法也以此为基础,任何无 ...
- 最新电脑公司最新GHOST WIN7系统32,64位极速安全版
系统来自系统妈:http://www.xitongma.com 电脑公司最新GHOST win7系统64位极速安全版 V2016年3月 系统简介 电脑公司ghost win7系统64位极速安全版集成了 ...
- 使用com.sun.imageio.plugins.png.PNGMetadata读取图片的元数据
所谓图片元数据,就是除了我们肉眼看到的图片内容外,隐藏在这些内容背后的一些技术数据. 本文介绍如何使用Java代码将一张图片的隐藏信息读取出来. 首先不需要下载任何额外的Java库,用JDK自带的库就 ...
- HDU 5097 Page Rank (模拟)
题目背景是以前用来对网页进行排名的Page Rank算法,是早期Google的革命性发明. 背后的原理是矩阵和图论.这个数学模型是由Google的创始人拉里·佩奇和谢尔盖·布林发现的. 如果一个网页被 ...
- Python-OpenCV中的cv2.inpaint()函数
概念 修复是图像插值.数字修复算法在图像插值,照片恢复,缩放和超分辨率等方面具有广泛的应用. 大多数人会在家里放一些旧的退化照片,上面有一些黑点,一些笔画等.你有没有想过恢复它?我们不能简单地在绘画工 ...
- opencv c++编译
g++ image2png.cpp -o test `pkg-config --cflags --libs opencv`
- 最全面的 python 字符串拼接总结(带注释版)
在 Python 中字符串连接有多种方式,这里简单做个总结,应该是比较全面的了,方便以后查阅. 加号连接 第一种,通过+号的形式: >>> a, b = 'hello', ' wor ...
- kvm笔记
1 virt-manager安装虚拟机无法使用键盘解决 今天远程用VNC登录服务器安装虚拟机,结果使用virt-manager安装虚拟机后在初始阶段无法使用键盘设置,这不雪崩了,后来来回试,找到了原因 ...