一、Tarjan求割点

对于无向图G,如果删除某个点x后,联通分量数目增加,则称点x是图G的割点。

如何求割点呢?一种简单的方法是采取枚举每个点,删除后用DFS求连通分量,这样时间复杂度是O(nm),显然不很优。

我们把在结点a为根的子树(不包括a)的点集即为 S(a),把不在a为根的子树中的点集即为 T(a)。

如图,如果将点2删除,那么点4可通过S(2)中的返祖边和T(2)连通,删除2对它没有影响;但S(2)中的点5,由于点5没有返祖边,因此和T(2)不连通,即点2是割点。

总结一下,得到如下结论:

对于某点x,若S(x)中存在至少一点y,满足y与T(x)之间没有任何边,则x是割点。

具体实现上,我们可以利用Tarjan算法记录dfn[x]和low[x]。于是问题转化成,结点x是否存在一个儿子y,使得low[y]≥dfn[x]。我们只需一次DFS即可,总时间复杂度O(n+m)。

注意:对根必须单判,根要有至少两个子树才能算作割点。

参考程序如下:

1 #include

2 #define int long long

3 using namespacestd;4 const int N=1e5+5;5 int n,m,x,y,cnt=1,hd[N],to[N<<1],nxt[N<<1],dfn[N],low[N],num,root;6 boolg[N];7 void add(int x,inty){8 to[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt;9 }10 void tarjan(intx){11 dfn[x]=low[x]=++num;12 int flag=0;13 for(int i=hd[x];i;i=nxt[i]){14 int y=to[i];15 if(!dfn[y]){16 tarjan(y),low[x]=min(low[x],low[y]);17 if(low[y]>=dfn[x]){18 flag++;19 if(x!=root||flag>1) g[x]=1;20 }21 }22 else low[x]=min(low[x],dfn[y]);23 }24 }25 signed main(){26 //freopen(".in","r",stdin);27 //freopen(".out","w",stdout);

28 scanf("%lld%lld",&n,&m);29 for(int i=1;i<=m;i++){30 scanf("%lld%lld",&x,&y);31 if(x==y) continue;32 add(x,y),add(y,x);33 }34 for(int i=1;i<=n;i++)35 if(!dfn[i]) root=i,tarjan(i);36 for(int i=1;i<=n;i++)37 if(g[i]) printf("%lld",i); //输出的是割点

38 return 0;39 }

二、Tarjan求割边

桥(割边):无向连通图中,去掉一条边,图中的连通分量数增加,则这条边,称为桥或者割边。

判断桥:一条无向边(x,y)是桥,当且仅当(x,y)为树枝边,且满足 dfn(x)

因为遍历的是无向图,所以从每个点x出发,总能访问到它的父节点fa。根据low的计算方法,(x,fa)属于搜索树上的边,且fa不是x的子节点,故不能用fa的时间戳来更新low[x]。

如果仅记录每个节点的父节点,会无法处理重边的情况。当x与fa之间有多条边时,(x,fa)一定不是桥。在这些重复的边中,只有一条算是“搜索树上的边”,其他的几条都不算。故有重边时,dfn[fa]能用来更新low[x]。

改为记录“递归进入每个节点的边的编号”。编号可认为是边在邻接表中存储的下标位置。把无向图的每一条边看做双向边,成对存储在下标里。若沿着编号为i的边递归进入了节点x,则忽略从x出发的编号i xor 1的边,通过其他边计算low[x]即可。

1 #include

2 #define int long long

3 using namespacestd;4 const int N=1e5+5;5 int n,m,x,y,cnt=1,hd[N],to[N<<1],nxt[N<<1],dfn[N],low[N],num;6 bool g[N<<1];7 void add(int x,inty){8 to[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt;9 }10 void tarjan(int x,intfa){11 dfn[x]=low[x]=++num;12 for(int i=hd[x];i;i=nxt[i]){13 int y=to[i];14 if(!dfn[y]){15 tarjan(y,i);16 low[x]=min(low[x],low[y]);17 if(low[y]>dfn[x]) g[i]=g[i^1]=1;18 }19 else if(i!=(fa^1)) low[x]=min(low[x],dfn[y]);20 }21 }22 signed main(){23 //freopen(".in","r",stdin);24 //freopen(".out","w",stdout);

25 scanf("%lld%lld",&n,&m);26 for(int i=1;i<=m;i++){27 scanf("%lld%lld",&x,&y);28 add(x,y),add(y,x);29 }30 for(int i=1;i<=n;i++)31 if(!dfn[i]) tarjan(i,0);32 for(int i=2;i

三、例题

Luogu P1656 炸铁路

题目链接 思路:直接求割边,然后排序即可。

1 #include

2 #define int long long

3 using namespacestd;4 const int N=1e5+5;5 int n,m,x,y,cnt=1,hd[N],to[N<<1],nxt[N<<1],dfn[N],low[N],num,sum;6 bool g[N<<1];7 structdata{8 intx,y;9 }a[N];10 boolcmp(data x,data y){11 if(x.x!=y.x) return x.xdfn[x]) g[i]=g[i^1]=1;25 }26 else if(i!=(fa^1)) low[x]=min(low[x],dfn[y]);27 }28 }29 signed main(){30 //freopen(".in","r",stdin);31 //freopen(".out","w",stdout);

32 scanf("%lld%lld",&n,&m);33 for(int i=1;i<=m;i++){34 scanf("%lld%lld",&x,&y);35 add(x,y),add(y,x);36 }37 for(int i=1;i<=n;i++)38 if(!dfn[i]) tarjan(i,0);39 for(int i=2;ia[i].y) swap(a[i].x,a[i].y);44 printf("%lld %lld\n",a[i].x,a[i].y);45 }46 return 0;47 }

Luogu P3388 「模板」割点(割顶)

题目链接 思路:板子题。直接上代码:

1 #include

2 #define int long long

3 using namespacestd;4 const int N=1e5+5;5 int n,m,x,y,cnt=1,hd[N],to[N<<1],nxt[N<<1],dfn[N],low[N],num,root,sum;6 boolg[N];7 void add(int x,inty){8 to[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt;9 }10 void tarjan(intx){11 dfn[x]=low[x]=++num;12 int flag=0;13 for(int i=hd[x];i;i=nxt[i]){14 int y=to[i];15 if(!dfn[y]){16 tarjan(y),low[x]=min(low[x],low[y]);17 if(low[y]>=dfn[x]){18 flag++;19 if(x!=root||flag>1) g[x]=1;20 }21 }22 else low[x]=min(low[x],dfn[y]);23 }24 }25 signed main(){26 //freopen(".in","r",stdin);27 //freopen(".out","w",stdout);

28 scanf("%lld%lld",&n,&m);29 for(int i=1;i<=m;i++){30 scanf("%lld%lld",&x,&y);31 if(x==y) continue;32 add(x,y),add(y,x);33 }34 for(int i=1;i<=n;i++)35 if(!dfn[i]) root=i,tarjan(i);36 for(int i=1;i<=n;i++)37 if(g[i]) sum++;38 printf("%lld\n",sum);39 for(int i=1;i<=n;i++)40 if(g[i]) printf("%lld",i);41 return 0;42 }

咕咕咕……先占个坑

我只会打板子啊

Dls教教我

tarjan算法 java_Tarjan算法 割点和桥相关推荐

  1. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

  2. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E) 割点: 对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点 割边(桥) 若对于e∈E,从图中删去边e之 ...

  3. tarjan算法 (割点和桥)

    最近刚学习了tarjan算法,发一篇博客写一下自己的心得和理解. 在了解割点和桥之前,我们先理解什么是双连通. 双连通和强连通分别是应用于无向图和有向图中的,那么在学习双连通之前,请自行学习求强连通分 ...

  4. tarjan算法求无向图的割点和桥

    tarjan算法求无向图的割点与桥 一篇tarjan算法求割点与桥的完整的解释,写的真的好认真 以下代码来自kuangbin的模板 4.5 图的割点.桥和双连通分支的基本概念 [点连通度与边连通度] ...

  5. 001.Tarjan算法:求解图的割点与桥(割边)

    简介: 割边和割点的定义仅限于无向图中.我们可以通过定义以蛮力方式求解出无向图的所有割点和割边,但这样的求解方式效率低.Tarjan提出了一种快速求解的方式,通过一次DFS就求解出图中所有的割点和割边 ...

  6. 南大算法设计与分析课程OJ答案代码(5)--割点与桥和任务调度问题

    问题 A: 割点与桥 时间限制: 1 Sec  内存限制: 5 MB 提交: 475  解决: 34 提交 状态 算法问答 题目描述 给出一个无向连通图,找到所有的割点和桥 输入 第一行:点的个数,如 ...

  7. 图论 —— 图的连通性 —— Tarjan 求割点与桥

    [概念] 1.割点 1)割点:删除某点后,整个图变为不连通的两个部分的点 2)割点集合:在一个无向图中删除该集合中的所有点,能使原图变成互不相连的连通块的点的集合 3)点连通度:最小割点集合点数 如上 ...

  8. 图论之tarjan真乃神人也,强连通分量,割点,桥,双连通他都会

    先来%一下Robert Tarjan前辈 %%%%%%%%%%%%%%%%%% 然后是热情感谢下列并不止这些大佬的博客: 图连通性(一):Tarjan算法求解有向图强连通分量 图连通性(二):Tarj ...

  9. tarjan求割点和桥(割边)模板

    tanjan算法相关概念 为了与有向图尽可能保持一致,我们将无向图的一条无向边拆分成两条单向边.两条边互为反向边. 从图中一点作为起点,进行DFS搜索遍历图,这样会得到一棵树,我们称之为DFS搜索树, ...

  10. tarjan求割点和桥(割边)

    tarjan求割点和桥 参考博客:tarjan求割点和桥(割边) 例题:割点 代码(重要的地方在代码中都有注释): #include<bits/stdc++.h> #define ll l ...

最新文章

  1. 在单元测试时指定HttpContext的各种Path
  2. 北京python培训班价格-北京python培训一对一
  3. mac下的apache项目发布出现403
  4. 下载linux操作系统一般的初始账号密码(虚拟机)
  5. windows编写第一个MFC程序
  6. HDOJ1394 Minimum Inversion Number【线段树】
  7. AIX的完整形式是什么?
  8. Python总结:RuntimeError: matplotlib does not support generators as input
  9. 虚拟dom_虚拟DOM与dom diff
  10. 微信上如何发送GIF动图
  11. 3.9 Spark 键值对RDD编程
  12. c语言教程求反符号,c语言“或”符号
  13. c++学习书籍推荐及理由
  14. 一个屌丝程序猿的人生(一百零九)
  15. java图片透明_Java实现对图片透明化处理
  16. Awvs详细使用教程
  17. 计算机类课题研究方法,课题研究方法
  18. andriod studio 运行项目时没有NDK(Android Studio如何更改JDK和SDK或者DNK的路径)
  19. 山大计算机学院夏令营2021,关于举办山东大学2021年暑期未来数学家夏令营的通知...
  20. MacOs 恢复系统后无法更新版本

热门文章

  1. 《数字图像处理》冈萨雷斯版 读书笔记(一)
  2. 1104报表背景知识
  3. 解决电信网络Echarts官网打不开的问题
  4. mongovue mysql_MongoDB 客户端 MongoVue
  5. linux c Make file 的生成
  6. Windows 10 下使用 VMPlayer 16 新建 CentOS 7 64位 虚拟机
  7. 计算机注册dll,电脑中注册dll文件和ocx文件的方法与操作步骤
  8. 优秀开源项目YYKit
  9. c语言项目图书馆借书,C语言打造—齐全的图书馆借阅系统
  10. 鲜花销售管理系统jsp全部代码_基于Java的鲜花销售管理系统设计与实现.zip