tarjan算法应用 割点 桥 双连通分量
tarjan算法的应用。
还需多练习…….遇上题目还是容易傻住
对于tarjan算法中使用到的Dfn和Low数组.
low[u]:=min(low[u],dfn[v])——(u,v)为后向边,v不是u的子树;
low[u]:=min(low[u],low[v])——(u,v)为树枝边,v为u的子树;
1.求割点:
割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点。
原理:若low[v]>=dfn[u],则u为割点。因low[v]>=dfn[u],则说明v通过子孙无法到达u的祖先。那么对于原图,去掉u后,必然会分成两个子图。
所以处理节点u时,先递归v的子节点,然后回溯至u时,如果满足low[v]>=dfn[u],则u为割点。
int tarjan(int x)
{
v[x]=1; //点的状态标记,1为已访问,2为割点
Dfn[x]=Low[x]=time++;
for(int i=head[x];i;i=next[i])
{
if(!v[ver[i]])
{
tarjan(ver[i]);
Low[x]=min(Low[x],Low[ver[i]]);
if(Dfn[x]<=low[ver[i]])
v[x]++;
}
else
Low[x]=min(low[x],Dfn[ver[i]]);
if((x==1&&v[x]>2)||(x>1&&v[x]>1)) //对第一个特判
v[x]=2;
else
v[x]=1;
}
}
2.求桥
桥(割边):删掉它之后,图必然会分裂为两个或两个以上的子图。
原理:若low[v]>dfn[u],则(u,v)为桥。由割点同理可得。但是由于可能存在重边,需要把一条无向边拆成的两条标号相同的有向边,记录每个点的父亲到它的边的标号,如果边(u,v)是v的父亲边,就不能用dfn[u]更新low[v]。这样如果遍历完v的所有子节点后,发现low[v]=dfn[v],说明u的父亲边(u,v)为割边。
void tarjan(int x)
{
v[x]=1;
Dfn[x]=Low[x]=time++;
for(int i=head[x];i;i=next[i])
{
if(!v[ver[i]])
{
p[ver[i]]=edge[i]; //记录父亲边
tarjan(ver[i]);
Low[x]=min(Low[x],Low[ver[i]]);
}
else if(p[x]!=edge[i]) //不是父亲边则更新
Low[x]=min(Low[x],Dfn[ver[i]]);
if(p[x]&&low[x]==dfn[x])
f[p[x]]=1; //为割边
}
}
3.点双连通分量
点双连通分支,在求割点的过程中就能把每个点双连通分支求出。建立一个栈,存储双连通分支。在搜索图时,每找到一条树枝边或后向边(非横叉边),就把这条边加入栈中。如果遇到某时满足DFS(u)<=Low(v),说明u是一个割点,同时把边从栈顶一个个取出,直到遇到了边(u,v),取出的这些边与其关联的点,组成一个点双连通分支。
if(dfn[u]==low[u])
{
scc++;
while(1) //记录每一个点属于的连通块
{
v=sta[top--];
instack[v]=0;
belong[v]=scc; //所取出的点即为双连通分支
if(v==u)
break;
}
}
}
4.边双连通分支。在求出所有的桥以后,把桥边删除,原图变成了多个连通块,则每个连通块就是一个边双连通分支。桥不属于任何一个边双连通分支,其余的边和每个顶点都属于且只属于一个边双连通分支。
5.一个有桥的连通图,如何把它通过加边变成边双连通图
首先求出所有的桥,然后删除这些桥边,剩下的每个连通块都是一个双连通子图。把每个双连通子图收缩为一个顶点,再把桥边加回来,最后的这个图一定是一棵树,边连通度为1。
统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf。则至少在树上添加(leaf+1)/2条边,就能使树达到边二连通,所以至少添加的边数就是(leaf+1)/2。
void Tarjan(int u,int fa)
{
int i,v;
low[u]=dfn[u]=++cnt;
sta[++top]=u;
instack[u]=1;
for(i=first[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(i==(fa^1))
continue;
if(!dfn[v])
{
Tarjan(v,i);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
scc++;
while(1) //记录每一个点属于的连通块
{
v=sta[top--];
instack[v]=0;
belong[v]=scc;
if(v==u)
break;
}
}
}
for(i=1;i<=n;i++)
{
for(j=first[i];j!=-1;j=edge[j].next)
{
v=edge[j].v;
if(belong[i]!=belong[v])
degree[belong[i]]++; //degree为1则为leaf
}
}
int sum=0;
for(i=1;i<=n;i++)
if(degree[i]==1)
sum++; 统计leaf数
}
tarjan算法应用 割点 桥 双连通分量的更多相关文章
- tarjan算法(割点/割边/点连通分量/边连通分量/强连通分量)
tarjan算法是在dfs生成一颗dfs树的时候按照访问顺序的先后,为每个结点分配一个时间戳,然后再用low[u]表示结点能访问到的最小时间戳 以上的各种应用都是在此拓展而来的. 割点:如果一个图去掉 ...
- [Tarjan系列] Tarjan算法求无向图的双连通分量
这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...
- Tarjan算法求割点
(声明:以下图片来源于网络) Tarjan算法求出割点个数 首先来了解什么是连通图 在图论中,连通图基于连通的概念.在一个无向图 G 中,若从顶点i到顶点j有路径相连(当然从j到i也一定有路径),则称 ...
- Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】
一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...
- (转)Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...
- 学习笔记--Tarjan算法之割点与桥
前言 图论中联通性相关问题往往会牵扯到无向图的割点与桥或是下一篇博客会讲的强连通分量,强有力的\(Tarjan\)算法能在\(O(n)\)的时间找到割点与桥 定义 若您是第一次了解\(Tarjan\) ...
- Tarjan算法与割点割边
目录 Tarjan算法与无向图的连通性 1:基础概念 2:Tarjan判断割点 3:Tarjan判断割边 Tarjan算法与无向图的连通性 1:基础概念 在说Tarjan算法求解无向图的连通性之前,先 ...
- 图的连通性——Tarjan算法&割边&割点
tarjan算法 原理: 我们考虑 DFS 搜索树与强连通分量之间的关系. 如果结点 是某个强连通分量在搜索树中遇到的第⼀个结点,那么这个强连通分量的其余结点肯定 是在搜索树中以 为根的⼦树中. 被称 ...
- Tarjan 算法求割点、 割边、 强联通分量
Tarjan算法是一个基于dfs的搜索算法, 可以在O(N+M)的复杂度内求出图的割点.割边和强联通分量等信息. https://www.cnblogs.com/shadowland/p/587225 ...
随机推荐
- 34 String、StringBuffer、StringBuilder
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间. StringBuffer是可变类,和线程安全的字符串操作类,任何对 ...
- SQL 行转列(列的值不规则的数目)
--创建一个临时表用来存储数据 create table #tmp_SNValue_Table (FieldName nvarchar(20), [Value] nvarchar(max)) inse ...
- 序列式容器————array
目录 介绍 1 构造函数 2 fill() 3 元素的获取 4 size() 5 empty() 6 front() 7 back() 8 get<n> 9 迭代器(待补充) 10 元素的 ...
- Redis配置文件全解
基本配置 port 6379 # 监听端口号,默认为 6379,如果你设为 0 ,redis 将不在 socket 上监听任何客户端连接. daemonize no #是否以后台进程启动 datab ...
- 一个优雅的图片裁剪插件vue-cropper
github: https://github.com/xyxiao001/vue-cropper
- OI常用的常数优化小技巧
注意:本文所介绍的优化并不是算法上的优化,那个就非常复杂了,不同题目有不同的优化.笔者要说的只是一些实用的常数优化小技巧,很简单,虽然效果可能不那么明显,但在对时间复杂度要求十分苛刻的时候,这些小的优 ...
- Hive数据导入Elasticsearch
Elasticsearch Jar包准备 所有节点导入elasticsearch-hadoop-5.5.1.jar /opt/cloudera/parcels/CDH-5.12.0-1.cdh5.12 ...
- linux cut sort wc sed>vi awk (文本处理)
cut: 显示切割的行数据 -f: 选择显示的列 (1: 显示第一列; 1,3: 显示第一列.第三列; 1-3: 显示第一列到第三列) -s: 不显示没有分隔符的行 -d: 自定义分隔符(' '空格 ...
- 把一个树莓派SD卡系统和文件迁移到空SD卡中
1.打开win32diskimager软件读出SD卡树莓派系统和文件到电脑的镜像文件中, 2.使用 SD card formatter 格式化SD卡 3.再用win32diskimager往空SD卡写 ...
- Java第一次学习总结
学习内容: 1.java是本学期刚刚接触新的一种编程语言,与大一C语言在语法上有很多相同之处,不同的是在很多问题上,更加简练,更加易于理解. 例如:输出水仙花数,从C语言近五十行代码缩短近十几行,数据 ...