[知识点]Tarjan算法
// 此博文为迁移而来,写于2015年4月14日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102vxnx.html
UPDATE(20180809):对代码和描述进行大量修改。
UPDATE(20151104):新增Tarjan算法核心代码。

#include <cstdio> #define MAXN 1005
#define MAXM 10005 int o, n, m, u, v, h[MAXN], ins[MAXN], dfn[MAXN], low[MAXN], tim, st[MAXN << ], t, tot, top[MAXN], ans[MAXN][MAXN]; struct Edge {
int v, next;
} e[MAXM]; int min(int a, int b) {
return a < b ? a : b;
} void add(int u, int v) {
o++, e[o] = (Edge) {v, h[u]}, h[u] = o;
} void tarjan(int o) {
dfn[o] = low[o] = ++tim, ins[o] = , st[++t] = o;
for (int x = h[o]; x; x = e[x].next) {
int v = e[x].v;
if (!dfn[v]) tarjan(v), low[o] = min(low[o], low[v]);
else if (ins[v] && dfn[v] < low[o]) low[o] = dfn[v];
}
if (dfn[o] == low[o]) {
int x; tot++;
do {
x = st[t--];
ins[x] = ;
ans[tot][++top[tot]] = x;
} while (x != o);
}
} int main() {
freopen("tarjan.in", "r", stdin);
freopen("tarjan.out", "w", stdout);
scanf("%d %d", &n, &m);
for (int i = ; i <= m; i++) scanf("%d %d", &u, &v), add(u, v);
for (int i = ; i <= n; i++) if (!dfn[i]) tarjan(i);
for (int i = ; i <= tot; i++) {
for (int j = ; j <= top[i]; j++) printf("%d ", ans[i][j]);
printf("\n");
}
return ;
}

#include <cstdio> #define MAXN 500005
#define MAXM 500005 int n, m, u[MAXN], v[MAXN], tw[MAXN], ts, p, to, tb[MAXN], th[MAXN];
int w[MAXN], b[MAXN], s, h[MAXN], o, lik[MAXN];
int dfn[MAXN], low[MAXN], ins[MAXN], st[MAXN], tot, t, tim;
int f[MAXN], ans; struct Edge {
int v, next;
} e[MAXM], te[MAXM]; int min(int a, int b) {
return a < b ? a : b;
} int max(int a, int b) {
return a > b ? a : b;
} void add(int u, int v, int t) {
if (t) to++, te[to] = (Edge) {v, th[u]}, th[u] = to;
else o++, e[o] = (Edge) {v, h[u]}, h[u] = o;
} void init() {
scanf("%d %d", &n, &m);
for (int i = ; i <= m; i++) scanf("%d %d", &u[i], &v[i]), add(u[i], v[i], );
for (int i = ; i <= n; i++) scanf("%d", &tw[i]);
scanf("%d %d", &ts, &p);
for (int i = ; i <= p; i++) scanf("%d", &o), tb[o] = ;
} void tarjan(int o) {
dfn[o] = low[o] = ++tim, ins[o] = , st[++t] = o;
for (int x = th[o]; x; x = te[x].next) {
int v = te[x].v;
if (!dfn[v]) tarjan(v), low[o] = min(low[v], low[o]);
else if (ins[v] && dfn[v] < low[o]) low[o] = dfn[v];
}
if (dfn[o] == low[o]) {
int x; tot++;
do x = st[t--], ins[x] = , lik[x] = tot; while (x != o);
}
} void rebuild() {
for (int i = ; i <= m; i++) if (lik[u[i]] != lik[v[i]]) add(lik[u[i]], lik[v[i]], );
for (int i = ; i <= n; i++) {
w[lik[i]] += tw[i];
if (i == ts) s = lik[i];
if (tb[i]) b[lik[i]] = ;
}
f[s] = w[s];
} void DFS(int o) {
if (b[o]) ans = max(ans, f[o]);
for (int x = h[o]; x; x = e[x].next) {
int v = e[x].v;
if (f[o] + w[v] > f[v]) f[v] = f[o] + w[v], DFS(v);
}
} int main() {
init();
for (int i = ; i <= n; i++) if (!dfn[i]) tarjan(i);
rebuild();
DFS(s);
printf("%d", ans);
return ;
}
[知识点]Tarjan算法的更多相关文章
- tarjan算法 POJ3177-Redundant Paths
参考资料传送门 http://blog.csdn.net/lyy289065406/article/details/6762370 http://blog.csdn.net/lyy289065406/ ...
- 有向图强连通分量的Tarjan算法
有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G ...
- 点/边 双连通分量---Tarjan算法
运用Tarjan算法,求解图的点/边双连通分量. 1.点双连通分量[块] 割点可以存在多个块中,每个块包含当前节点u,分量以边的形式输出比较有意义. typedef struct{ //栈结点结构 保 ...
- 割点和桥---Tarjan算法
使用Tarjan算法求解图的割点和桥. 1.割点 主要的算法结构就是DFS,一个点是割点,当且仅当以下两种情况: (1)该节点是根节点,且有两棵以上的子树; (2)该节 ...
- Tarjan算法---强联通分量
1.基础知识 在有向图G,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子 ...
- (转载)LCA问题的Tarjan算法
转载自:Click Here LCA问题(Lowest Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两 ...
- 强连通分量的Tarjan算法
资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tar ...
- Tarjan 算法&模板
Tarjan 算法 一.算法简介 Tarjan 算法一种由Robert Tarjan提出的求解有向图强连通分量的算法,它能做到线性时间的复杂度. 我们定义: 如果两个顶点可以相互通达,则称两个顶点强连 ...
- 【小白入门向】tarjan算法+codevs1332上白泽慧音 题解报告
一.[前言]关于tarjan tarjan算法是由Robert Tarjan提出的求解有向图强连通分量的算法. 那么问题来了找蓝翔!(划掉)什么是强连通分量? 我们定义:如果两个顶点互相连通(即存在A ...
随机推荐
- Linux Shell 高级编程技巧2----shell工具
2.shell工具 2.1.日志文件 简介 创建日志文件是很重要的,记录了重要的信息.一旦出现错误,这些信息对于我们排错是非常有用的:监控的信息也可以记录到日 ...
- Shell编程基础教程1--Shell简介
1.Shell简介 1.1.查看你系统shell信息 cat /etc/shell 命令可以获取Linux系统里面有多少种shell程序 echo $SHELL 命令可以查看当前你所使用的shell是 ...
- 【JAVA解析XML文件实现CRUD操作】
一.简介. 1.xml解析技术有两种:dom和sax 2.dom:Document Object Model,即文档对象模型,是W3C组织推荐的解析XML的一种方式. sax:Simple API f ...
- 无废话ExtJs 入门教程六[按钮:Button]
无废话ExtJs 入门教程六[按钮:Button] extjs技术交流,欢迎加群(201926085) 继上一节内容,我们在表单里加了个两个按钮“提交”与重置.如下所示代码区的第68行位置, butt ...
- MVA Universal Windows Apps系列学习笔记1
昨天晚上看了微软的Build 2015大会第一天第一场演讲,时间还挺长,足足3个小时,不过也挺震撼的.里面提到了windows 10.Microsoft edge浏览器.Azure云平台.Office ...
- HDU2296 Ring(AC自动机 DP)
dp[i][j]表示行走i步到达j的最大值,dps[i][j]表示对应的串 状态转移方程如下: dp[i][chi[j][k]] = min(dp[i - 1][j] + sum[chi[j][k]] ...
- Codeforces Round #363 LRU(概率 状压DP)
状压DP: 先不考虑数量k, dp[i]表示状态为i的概率,状态转移方程为dp[i | (1 << j)] += dp[i],最后考虑k, 状态表示中1的数量为k的表示可行解. #incl ...
- revert merge会出现的问题
比如当我们git revert的时候, git revert Git会抱怨: is a merge but no -m option was given 这是因为你revert的那个commit是一个 ...
- golang 索引
入门的基础路线 a Tour of GoEffective GoGo By Example 以上的三部分通读算是入门. 4个重要的组成部分 1. 基础知识2. 并发特性3. 异常处理4. 常用开源项目 ...
- hdu 2509 博弈 *
多堆的情况要处理好孤单堆 #include<cstdio> #include<iostream> #include<algorithm> #include<c ...