Tarjan算法及其应用

引入

tarjan算法可以在图上求解LCA,强连通分量,双联通分量(点双,边双),割点,割边,等各种问题。

这里简单整理一下tarjan算法的几个应用。

LCA

http://www.cnblogs.com/mjtcn/p/6852646.html

强联通分量

有向图的

强联通:在一个有向图G里,设两个点 a b 发现,由a有一条路可以走到b,由b又有一条路可以走到a,我们就叫这两个顶点(a,b)强连通。

强连通图: 如果 在一个有向图G中,每两个点都强连通,我们就叫这个图,强连通图。

强连通分量:在一个有向图G中,有一个子图,这个子图每2个点都满足强连通,我们就叫这个子图叫做 强连通分量 [分量:把一个向量分解成几个方向的向量的和,那些方向上的向量就叫做该向量(未分解前的向量)的分量]

http://www.cnblogs.com/mjtcn/p/7599217.html

边双联通分量

无向图的

边双联通图:如果在一个无向图中,任意两点至少存在两条不重复路径,则称该图为边双连通的。

边双联通分量:边双连通的极大子图称为边双连通分量

原理和强联通分量的求法差不多。

 void tarjan(int u,int fa) {
dfn[u] = low[u] = ++tn;
st[++top] = u;
vis[u] = true;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u],low[v]);
}
else if (vis[v] && v!=fa)
low[u] = min(low[u],dfn[v]);
}
if (dfn[u] == low[u]) {
++cnt;
do {
vis[st[top]] = false;
bel[st[top]] = cnt;
top--;
} while (st[top+] != u);
}
}

简单点可以这样写,low数组可以有bel数组的作用

 void tarjan(int u,int fa) {
dfn[u] = low[u] = ++tn;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
tarjan(v,u);
low[u] = min(low[u],low[v]);
}
else if (dfn[v] < dfn[u] && v != fa)
low[u] = min(low[u],dfn[v]);
}
}

点双联通分量

无向图的

留坑

割点

图的割点

在一个无向连通图中,如果删除某个顶点后,连通分量数目增加,称这样的点为割点(或者称割顶)。

朴素的求法O(n(n+m)),尝试删除每个点,dfs判断是否联通。

tarjan算法复杂度O(n+m),线性!!!

割点的条件:

  • 根节点:它的子节点中有多个联通块。
  • 非根节点:点u及其后代中没有点连向u的祖先(可以连回u)

所以只要让low[v] >= dfn[u]即可。

 void tarjan(int u,int fa) {
low[u] = dfn[u] = ++tn;
int cnt_son = ;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
cnt_son++;
tarjan(v,u);
low[u] = min(low[u],low[v]);
if (low[v] >= dfn[u]) // 第二种情况
iscut[u] = true;
}
else if (dfn[v] < dfn[u] && v != fa)
low[u] = min(low[u],dfn[v]);
}
if (fa< && cnt_son==) iscut[u] = false; // 第一种情况
}

割边

无向图

在一个无向连通图中,如果删除某条边后,图不再连通,这条边就是割边(桥)。

如果u的一个子节点v,它的所有子节点及其自己都不能连回u的祖先,这里包括也不能连向u,那么u-v,就是一个割边

代码只要改一个地方,low[v] > dfn[u]

 void tarjan(int u,int fa) {
dfn[u] = low[u] = ++tn;
for (int i=head[u]; i; i=e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
tarjan(v,u);
low[u] = min(low[u],low[v]);
if (low[v] > dfn[u]) {
printf("%d %d\n",u,v);
}
}
else if (dfn[v] < dfn[u] && v != fa)
low[u] = min(low[u],dfn[v]);
}
}

例题

poj 3352 Road Construction

求最少添加几条边才能使所给无向图变成边双连通图。

求出边双,缩点成一个树,之后统计树上的点度数为1的点的个数cnt,(cnt+1)/2就是答案。

定理:任意一颗无向图的树,成为双连通图,则需要增加的边数为(这棵树上所有度数为1的结点的个数+1)/2。

luogu P2746 [USACO5.3]校园网Network of Schools 

1.求最少让几个人知道就可以做到让所有的人都知道信息,最少知道的人的数目即为缩完点后入度为零的点的个数

2.最少加入几条边就可以使一个树变成一个强连通图,加的边的条数即为缩完点后 Max(入度为零的点的个数,出度为零的点的个数)

定理:任意一棵有向图的树,成为强联通分量,则需要增加的边数为max(入度为0的点的个数,出度为0的点的个数)

 

P3119 [USACO15JAN]草鉴定Grass Cownoisseur

求改变一条边的方向,有向图中包含1的强联通分量最大。

缩点所有的强联通分量,然后拓扑求最长链到1的距离,枚举改那条边

P2515 [HAOI2010]软件安装

tarjan缩点+树形dp

 

 

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. VS连接Access数据库--连接字符串及执行查询语句的方法(增删改查,用户名查重,根据用户获取密码查询)

    ACCESS数据的连接及语句执行操作,不难,久不用会生疏,每次都要找资料,干脆自己整理下,记录下来,需要的时候,直接查看,提高效率.也供初学者参考 1.连接字符串 public static stri ...

  2. 记录:swift学习笔记1-2

    swift还在不断的更新做细微的调整,都说早起的鸟儿有虫吃,那么我们早点出发吧,趁着国内绝大多数的coder们还没有开始大范围普遍应用. 网上有些大神说:swift很简单!我不同意这个观点,假如你用h ...

  3. Kendo UI 初始化 Data 属性

    初始化 Data 属性 前面在介绍准备 Kendo UI 开发环境时我们使用 jQuery 的方法将一个  HTML 元素转换成一个 Kendo UI 控制项: $(“#datepicker”).ke ...

  4. 在Windows Server 2012中搭建SQL Server 2012故障转移集群

    OK~ WSFC 2012 R2 年度盛宴开始~ 在本文中,老王将用一系列的场景,把动态仲裁,动态见证,票数调整,LowerQuorumPriorityNodeID,阻止仲裁等群集仲裁技术串起来,完成 ...

  5. 使 windows 无需输入开机密码自动进入系统

    步骤 运行netplwiz: 勾去图中所示复选框,确定后输入密码.

  6. HDU - 5493 Queue 2015 ACM/ICPC Asia Regional Hefei Online(线段树)

    按身高排序,每个人前面最高的人数有上限,如果超出上限说明impossible, 每次考虑最小的人,把他放在在当前的从左往右第k+1个空位 因为要求字典序最小,所以每次k和(上限-k)取min值. 没有 ...

  7. UVA11019 Matrix Matcher (AC自动机)

    二维的矩阵匹配,把模式矩阵按列拆开构造AC自动机,记录行号(为了缩点判断). 把T矩阵按行匹配,一旦匹配成功,在假想的子矩阵左上角位置加一.最后统计总数. 因为所有模式串长度一样,不用维护last数组 ...

  8. PHP程序Laravel框架的优化技巧

    Laravel是一套简洁.优雅的php Web开发框架(PHP Web Framework).它可以让你从杂乱的代码中解脱出来,可以帮你构建一个完美的网络app,而且每行代码都简洁.富于表达力.而性能 ...

  9. 【PowerShell语音计算器】

    [PowerShell语音计算器]带中文发音功能的计算器程序,支持鼠标和小键盘输入,支持多种数值转人民币大写,如:123.4--->壹佰贰拾叁点肆圆. 版本号 1.51 下载:http://fi ...

  10. python_92_面向对象初体验

    class dog: def __init__(self,name): self.name=name def bulk(self): print('%s汪汪汪!'%self.name) d1=dog( ...