tarjan算法--求解无向图的割点和桥
1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥
也就是说 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥
2.割点:无向连通图中,如果删除某点后,图变成不连通,则称该点为割点。
求取割点:
1》当前节点为树根的时候,条件是“要有多余一棵子树”(如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了。
2》当前节点U不是树根的时候,条件是“low[v]>=dfn[u]”,也就是在u之后遍历的点,能够向上翻,最多到u,如果能翻到u的上方,那就有环了,去掉u之后,图仍然连通。保证v向上最多翻到u才可以
树边,前向边,后向边,横叉边
图进行DFS会得到一棵DFS树(森林)
vis = 0,表示该顶点没没有被访问
vis = 1,表示该顶点已经被访问,但其子孙后代还没被访问完,也就没从该点返回
vis = 2,,表示该顶点已经被访问,其子孙后代也已经访问完,也已经从该顶点返回DFS过程中,对于一条边u->v
vis[v] = 0,说明v还没被访问,v是首次被发现,u->v是一条树边
vis[v] = 1,说明v已经被访问,但其子孙后代还没有被访问完(正在访问中),而u又指向v?说明u就是v的子孙后代(v都访问过了),u->v是一条后向边,因此后向边又称返祖边
vis[v] = 3,z说明v已经被访问,其子孙后代也已经全部访问完,u->v这条边可能是一条横叉边,或者前向边注意:树边,后向边,前向边,都有祖先,后裔的关系,但横叉边没有,u->v为横叉边,说明在这棵DFS树中,它们不是祖先后裔的关系它们可能是兄弟关系,堂兄弟关系,甚至更远的关系,如果是dfs森林的话,u和v甚至可以在不同的树上
在很多算法中,后向边都是有作用的,但是前向边和横叉边的作用往往被淡化,其实它们没有太大作用。
一直有个疑惑,这一天也就在看这个地方就是优化low数组的时候,如果自己的儿子节点没有被访问过,那么好说我们更新维护low数组是low[u] = min(low[u],low[v])————应付的情况就是子节点通过另一条路径访问到了祖先节点,但是当访问到的字节点被访问过的时候,为什么就要这么更新low数组low[u] = min(low[u],dfn[v])这个我没怎么想明白,后来看到了一个实例:
一个图(v,e)点为1,2,3,4,5,边有(1,2),(2,3),(3,1),(3,4),(4,5),(5,3)令1为树根。显然3为割点。不妨假设搜索顺序是(1,2),(2,3),(3,1),(3,4),(4,5),(5,3)搜索到(3,1)的时候,更新low[3] = dfn[1] = 1后搜索(3,4)、(4,5),(5,3),发现3已经遍历,那么如果此时采用low[u] = min(low[u], low[v])的话,会更新low[5] = low[3] = 1,回溯到4,low[4] = low[5] = 1,回溯到3,low[3] = low[4] = 1,然后比较发现low[4] < dfn[3],判断出3不是割点,算法错误。
所以也就是为了避免那个被访问过的点已经属于了一个联通分量了这样的话就会造成错误的联通分量融合的情况,这样也只是表面上明白了,还没有完全透彻,后续再捂捂
初始准备
const int maxn = 20010;
int n;
struct node{
int to,pre;
}e[maxn];
int id[maxn],cnt;
int index;
int low[maxn],dfn[maxn];
int cut_point[maxn];
链式前向星存储边 + index模拟时间戳 + low数组表示的意思是与"u节点及其子孙节点"相连的最先被访问到的点的访问序号。表示u节点最早可从那个节点访问到 + dfn数组为这个点的dfs访问次序
初始化过程
void init()
{
cnt = ;
index = ;
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(id,-,sizeof(id));
memset(cut_point,,sizeof(cut_point));
}
加边函数
void add(int from,int to)
{
e[cnt].to = to;
e[cnt].pre = id[from];
id[from] = cnt++;
}
tarjan算法
注释也差不多啦
访问一个点的时候初始化两个数组,记录根节点的子树数目,对于没有访问过的回溯时两种方法判断是否为为割点
void tarjan(int u,int fa)
{
int son = 0;
dfn[u] = low[u] = ++index;
for(int i = id[u];~i;i = e[i].pre)
{
int v = e[i].to;
if(!dfn[v])//目标点没有被访问过
{
tarjan(v,u);//先访问
son++;//记录儿子数目 low[u] = min(low[u],low[v]);//更新回溯的值 if(dfn[u] <= low[v] && u != 1)//如果不是数根,而且子节点回不到父节点及其以上
cut_point[u] = 1;
if(u == 1 && son > 1)//对于根节点,如果有两个及其以上的子树,那么肯定是割点
cut_point[u] = 1;
}
else//目标点被访问过,有两种可能
//1.从开始点一个环过来的,很简单对于low数组的更新都一样
//2.从另一个点延伸过来的,那就代表被访问过的点的low数组已经
//被那个强连通分量更新了,所以我们采用他的访问次数进行更新
low[u] = min(low[u],dfn[v]);
}
}
好了接下来就是根据题目更新了
int get_cnt()
{
int ans = 0;
tarjan(1,1);
for(int i = 1;i <= n;i++)
{
if(cut_point[i])
ans++;
}
return ans;
}
int main()
{
while(~scanf("%d",&n),n)
{
init();
int s,t;
while(~scanf("%d",&s),s)
{
while(getchar() != '\n')
{
scanf("%d",&t);
add(s,t);
add(t,s);
}
}
printf("%d\n",get_cnt());
}
return 0;
}
tarjan算法--求解无向图的割点和桥的更多相关文章
- tarjan算法--求无向图的割点和桥
一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中 ...
- Tarjan算法初探(3):求割点与桥以及双连通分量
接上一节Tarjan算法初探(2):缩点 在此首先提出几个概念: 割点集合:一个无向连通图G 若删除它的一个点集 以及点集中所有点相连的边(任意一端在点集中)后 G中有点之间不再连通则称这个点集是它的 ...
- [Tarjan系列] Tarjan算法求无向图的双连通分量
这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...
- [Tarjan系列] Tarjan算法求无向图的桥和割点
RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...
- Tarjan无向图的割点和桥(割边)全网详解&算法笔记&通俗易懂
更好的阅读体验&惊喜&原文链接 感谢@yxc的腿部挂件 大佬,指出本文不够严谨的地方,万分感谢! Tarjan无向图的割点和桥(割边) 导言 在掌握这个算法前,咱们有几个先决条件. [ ...
- 求 无向图的割点和桥,Tarjan模板
/* 求 无向图的割点和桥 可以找出割点和桥,求删掉每个点后增加的连通块. 需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重 */ const int MAXN = 10010; cons ...
- tarjan算法求无向图的桥、边双连通分量并缩点
// tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...
- Tarjan算法:求解图的割点与桥(割边)
简介: 割边和割点的定义仅限于无向图中.我们可以通过定义以蛮力方式求解出无向图的所有割点和割边,但这样的求解方式效率低.Tarjan提出了一种快速求解的方式,通过一次DFS就求解出图中所有的割点和割边 ...
- tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)
基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...
随机推荐
- 789A Anastasia and pebbles
A. Anastasia and pebbles time limit per test 1 second memory limit per test 256 megabytes input stan ...
- 手机端适配方案 媒体查询和flexbale
方法一 flexible 一.npm 包安装 lib-flexible 淘宝适配方案 px2rem px自动转rem npm install lib-flexible --save npm insta ...
- 采用RedisLive监控Redis服务——安装手册
#1.gcc编译环境确认 .tgz cd Python- ./configure /bin/python2. /usr/bin/python #运行python查看版本 python -V #进行更改 ...
- JSP动作
JSP动作元素在请求处理阶段起作用,他们会被转换成Java代码来执行操作,如访问一个Java对象或调用方法. JSP动作元素是用XML语法写成的. 动作元素基本上都是预定义的函数,JSP规范定义了一系 ...
- read temperature
button1, button2, richtexbox1, serialport1, using System;using System.Collections.Generic;using Syst ...
- JS浏览器Session存取数据
vm.indexdata.indexId = id; vm.indexdata.indexName = name; var tempIndex = JSON.stringify(vm.indexdat ...
- mysql cmd 无法登录
第一次折腾mysql诉苦记 版本注明: mysql 5.7.21 本地部署mysql,配置完成后(配置没有问题) cmd命令连接mysql: mysql -uroot -p 提示: ERROR 104 ...
- Oracle12c的卸载
之前电脑装了Oracle12c 现在希望删除重新安装: 参照教程: http://jingyan.baidu.com/article/642c9d34e1cbdd644a46f7de.html E:\ ...
- windows 2003端口80system进程占用的情况
1.首先是http服务 a. 位置 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTPb. 把 REG_DWORD 类型的项 Start ...
- CSS-弹性布局-动画-过渡
1.弹性布局 1.项目的属性 该组属性只能设置在某项目元素上,只控制一个项目,是不影响容器以及其他项目的效果. 1.order 作用:定义项目的排列顺序,值越小,越靠近起点,默认值是0 取值:整数数字 ...