图论 —— 图的连通性 —— Tarjan 求割点与桥
【概念】
1.割点
1)割点:删除某点后,整个图变为不连通的两个部分的点
2)割点集合:在一个无向图中删除该集合中的所有点,能使原图变成互不相连的连通块的点的集合
3)点连通度:最小割点集合点数
如上图,若去掉 0,则图被分成 12 和 34 两个连通分量;若去掉 3,则图被分成 012 和 4 两个连通分量。
故:0、3 是割点,两者是一个割点集,点连通度是 2
2.桥
1)桥(割边):删除某边后,使得连通图变为不连通的图,一图中可能有多条割边
2)割边集合:所有割边的集合
3)边连通度:最小割边集合边数
如上图,去掉 5-6,2-5 后不再连通,图被分为 1234、5、6 三个连通分量
故:5-6、2-5 是割边,两者组成的集是割边集,边连通度是 2
【原理】
1.求割点
对于一棵 DFS 搜索树:
1)根结点:当且仅当根节点至少有两个儿子时,其是割点
2)其他点:对于其他点 v,当仅有一个儿子 u 时,从 u 或 u 的后代出发,没有指向 v 祖先(不含 v)的边,则删除 v后,u 和 v 的父亲不连通时,v 是割点
2.求桥
对于边 (u,v),若发现 v 和它的后代不存在一条连接 u 或其祖先的边,则删除 (u,v) 后 u 和 v 不连通,因此边 (u,v) 为桥
【过程】
1.求割点
1)对图进行 Tarjan 算法,得到 dfn 和 low 两个数组
2)每遍历一个新的 u 的儿子 v 都记录个数
3)low[u] 值更新后进行以下判断(前提:v 未被遍历):
① u 为树根,且儿子个数大于 1
② u 不为树根,但 low[v]>=dfn[u]
满足以上任意条件 u 便为割点,记录在一数组里,Tarjan 完成后再输出即可(中途输出会重复)
2.求桥
判断原则:若 low[v]>dfn[u],则 (u,v) 为割边。
由于有的图有重边,因此不好通过上述判断原则来处理,故使用以下方法:
1)对图进行 Tarjan 算法,得到 dfn 和 low 两个数组
2)形参加上 father,作用为记录 u 的父亲节点,避免在遍历 v 时遇到重边重新更新 low[u]
3)在 v 已被遍历的位置加上判断:如果 v 点等于 father,那么就不更新 low[u] 值
4)Tarjan算法结束后,遍历所有节点u及其子节点v,如果 low[u]==low[v],那么这条边就为割边
【实现】
1.先将数据保存下来,再求割点与桥
int n,m;
int low[N],dfn[N];
vector<int>G[N];
bool is_cut[N];//记录是否为割点
int father[N];
int tim;//时间戳
void Tarjan(int x,int pre){father[x]=pre;//记录每一个点的父亲dfn[x]=low[x]=tim++;//每找到一个新点,纪录当前节点的时间戳for(int i=0;i<G[x].size();i++){int y=G[x][i];//当前结点的下一结点if(dfn[y]==-1){//若未被访问过Tarjan(y,x);low[x]=min(low[x],low[y]);}else if(pre!=y)//假如k是i的父亲的话,那么这就是无向边中的重边,有重边那么一定不是桥low[x]=min(low[x],dfn[y]);//可能dfn[k]!=low[k],所以不能用low[k]代替dfn[k],否则会上翻过头}
}int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;++i){int x,y;scanf("%d%d",&x,&y);G[x].push_back(y);G[y].push_back(x);}tim=0;memset(low,-1,sizeof(low));memset(dfn,-1,sizeof(dfn));memset(father,0,sizeof(father));memset(is_cut,false,sizeof(is_cut));Tarjan(1,0);//先Tarjan求出dfn和low数组int root=0;for(int i=2;i<=n;i++){//统计根节点子树的个数,根节点的子树个数>=2,即为割点int temp=father[i];if(temp==1)root++;else{if(low[i]>=dfn[temp])//割点的条件is_cut[temp]=true;}}if(root>1)is_cut[1]=true;//打印割点for(int i=1;i<=n;++i)if(is_cut[i])printf("%d ",i);printf("\n");for(int i=1;i<=n;++i){int temp=father[i];if(temp>0&&low[i]>dfn[temp])//桥的条件printf("%d,%d\n",temp,i);}return 0;
}
2.在 Tarjan 的过程中求桥
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 1000000+5;
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
using namespace std;struct Edge{int from,to,next;int cut;//记录该边是否为桥Edge(){}Edge(int from,int to,int next,int cut):from(from),to(to),next(next),cut(cut){}
}edge[N];
int n,m;
int head[N],edgeNum;
int dfn[N],low[N];
int block_cnt;
void addEdge(int from,int to){//添边edge[edgeNum]=Edge(from,to,head[from],false);head[from]=edgeNum++;
}
void tarjin(int x,int father){low[x]=dfn[x]=++block_cnt;for(int i=head[x];i!=-1;i=edge[i].next){int y=edge[i].to;if(!dfn[y]){tarjin(y,x);if(low[x]>low[y])low[x]=low[y];if(low[y]>dfn[x])edge[i].cut=true;}else if(y!=father)low[x]=min(low[x],dfn[y]);}
}
int main(){scanf("%d%d",&n,&m);memset(dfn,0,sizeof(dfn));memset(head,-1,sizeof(head));edgeNum=0;while(m--){int x,y;scanf("%d%d",&x,&y);addEdge(x,y);addEdge(y,x);}tarjin(1,1); for(int i=0;i<edgeNum;i++)//打印桥if(edge[i].cut)printf("%d %d\n",edge[i].from,edge[i].to);return 0;
}
图论 —— 图的连通性 —— Tarjan 求割点与桥相关推荐
- 图论 —— 图的连通性 —— Tarjan 求双连通分量
[概念] 1.双连通分量:对于一个无向图,其边/点连通度大于1,满足任意两点之间,能通过两条或两条以上没有任何重复边的路到达的图,即删掉任意边/点后,图仍是连通的 2.分类: 1)点双连通图:点连通度 ...
- 图论 —— 图的连通性 —— Tarjan 求强连通分量
[概述] Tarjan 算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树. 搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量. [ ...
- tarjan求割点和桥(割边)
tarjan求割点和桥 参考博客:tarjan求割点和桥(割边) 例题:割点 代码(重要的地方在代码中都有注释): #include<bits/stdc++.h> #define ll l ...
- tarjan求割点和桥(割边)模板
tanjan算法相关概念 为了与有向图尽可能保持一致,我们将无向图的一条无向边拆分成两条单向边.两条边互为反向边. 从图中一点作为起点,进行DFS搜索遍历图,这样会得到一棵树,我们称之为DFS搜索树, ...
- 图论 —— 图的连通性 —— Tarjan 缩点
缩点常应用于给一个有向图,求在图中最少要加多少条边能使得该图变成一个强连通图 首先求出该图的各个强连通分量,然后把每个强连通分量看出一个点(即缩点),最后得到了一个有向无环图(DAG) 对于一个DAG ...
- 图论 —— 图的连通性
[基本概念] 1.连通图与连通分量 1)连通图:无向图 G 中,若对任意两点,从顶点 Vi 到顶点 Vj 有路径,则称 Vi 和 Vj 是连通的,图 G 是一连通图 2)连通分量:无向图 G 的连通子 ...
- 第1节 连通性强连通、割点和桥(一)
文章目录 无向图割点.桥.双连通分量 Tarjan算法求割点和桥(割边) 代码: 边双连通分量 和 点双连通分量 代码 边双连通分量 和 点双连通分量 的缩点 有向图的弱连通与强连通 强连通分量 Ko ...
- poj1144 - tarjan求割点
何为割点?也就是题目中的关键点.在一个无向图中,去掉一个点,这个无向图会变成多个子图,那么这个点就叫做割点 同理,割边也是如此,如果去掉一条边,能让无向图变成多个子图,那么这条边叫做割边,所谓的桥. ...
- [UVA315]Network(tarjan, 求割点)
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
最新文章
- 布尔(bool)值需注意事项
- View绘制原理 —— 画在哪?
- monkey测试===如何获取android app的Activity
- 如何绕过浏览器的弹窗拦截机制
- vue点击图片后复制图片url_简单漂亮的(图床工具)开源图片上传工具——PicGo...
- boost::metaparse::v1::impl::empty_string相关用法的测试程序
- httpRuntime 一点经验---引
- TOMCAT常用优化
- 【2016年第1期】从政策驱动到技术践行:大数据开辟可持续发展研究新途径
- python-虚拟环境的创建与使用-针对linu系统
- 手动启动_电站首台机组首次手动开机启动一次性成功
- html 禁用自动跳转,javascript 实现页面跳转,禁止返回上一页【转】
- 推荐系统实践:从多领域优化到AutoML框架
- mysql通用mapper_通用Mapper(Mybatis)
- 记账本------7
- 怎样一次性压缩多张图片?这个无损批量压缩图片方法送给你
- angularJs - 弹窗
- 那位仁兄或者仁姐能给小弟一个菊花论坛的邀请码
- 隐私集合求交(PSI)协议研究综述
- springBoot的shiro的简单项目部署
热门文章
- 这5种思维模式,大牛产品经理都在用
- 最暖数据: 除夕有6.88亿人用微信红包传递狗年祝福
- 如果去掉数学前后的空格_数学家们是怎么玩趣味拼图游戏的?
- 为什么不可以使用哈曼顿距离_哈曼卡顿SOUNDSTICKS4全新一代无线水晶蓝牙音箱评测...
- 客制化键盘键位修改_IQUNIX Slim87 RGB机械键盘评测
- 微服务面试必问的Dubbo,这么详细还怕自己找不到工作?
- 为什么蚂蚁金服架构师建议从Zookeeper开始提升技术水平?
- springMVC整合swagger(亲自试验完全可用)
- 【JEECG 官方】技术支持联系方式
- 专刊文章 - Web UI框架引领J2EE新开发模式(代码生成器+手工merge半智能开发)