【概念】

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 求割点与桥相关推荐

  1. 图论 —— 图的连通性 —— Tarjan 求双连通分量

    [概念] 1.双连通分量:对于一个无向图,其边/点连通度大于1,满足任意两点之间,能通过两条或两条以上没有任何重复边的路到达的图,即删掉任意边/点后,图仍是连通的 2.分类: 1)点双连通图:点连通度 ...

  2. 图论 —— 图的连通性 —— Tarjan 求强连通分量

    [概述] Tarjan 算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树. 搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量. [ ...

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

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

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

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

  5. 图论 —— 图的连通性 —— Tarjan 缩点

    缩点常应用于给一个有向图,求在图中最少要加多少条边能使得该图变成一个强连通图 首先求出该图的各个强连通分量,然后把每个强连通分量看出一个点(即缩点),最后得到了一个有向无环图(DAG) 对于一个DAG ...

  6. 图论 —— 图的连通性

    [基本概念] 1.连通图与连通分量 1)连通图:无向图 G 中,若对任意两点,从顶点 Vi 到顶点 Vj 有路径,则称 Vi 和 Vj 是连通的,图 G 是一连通图 2)连通分量:无向图 G 的连通子 ...

  7. 第1节 连通性强连通、割点和桥(一)

    文章目录 无向图割点.桥.双连通分量 Tarjan算法求割点和桥(割边) 代码: 边双连通分量 和 点双连通分量 代码 边双连通分量 和 点双连通分量 的缩点 有向图的弱连通与强连通 强连通分量 Ko ...

  8. poj1144 - tarjan求割点

    何为割点?也就是题目中的关键点.在一个无向图中,去掉一个点,这个无向图会变成多个子图,那么这个点就叫做割点 同理,割边也是如此,如果去掉一条边,能让无向图变成多个子图,那么这条边叫做割边,所谓的桥. ...

  9. [UVA315]Network(tarjan, 求割点)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

最新文章

  1. 布尔(bool)值需注意事项
  2. View绘制原理 —— 画在哪?
  3. monkey测试===如何获取android app的Activity
  4. 如何绕过浏览器的弹窗拦截机制
  5. vue点击图片后复制图片url_简单漂亮的(图床工具)开源图片上传工具——PicGo...
  6. boost::metaparse::v1::impl::empty_string相关用法的测试程序
  7. httpRuntime 一点经验---引
  8. TOMCAT常用优化
  9. 【2016年第1期】从政策驱动到技术践行:大数据开辟可持续发展研究新途径
  10. python-虚拟环境的创建与使用-针对linu系统
  11. 手动启动_电站首台机组首次手动开机启动一次性成功
  12. html 禁用自动跳转,javascript 实现页面跳转,禁止返回上一页【转】
  13. 推荐系统实践:从多领域优化到AutoML框架
  14. mysql通用mapper_通用Mapper(Mybatis)
  15. 记账本------7
  16. 怎样一次性压缩多张图片?这个无损批量压缩图片方法送给你
  17. angularJs - 弹窗
  18. 那位仁兄或者仁姐能给小弟一个菊花论坛的邀请码
  19. 隐私集合求交(PSI)协议研究综述
  20. springBoot的shiro的简单项目部署

热门文章

  1. 这5种思维模式,大牛产品经理都在用
  2. 最暖数据: 除夕有6.88亿人用微信红包传递狗年祝福
  3. 如果去掉数学前后的空格_数学家们是怎么玩趣味拼图游戏的?
  4. 为什么不可以使用哈曼顿距离_哈曼卡顿SOUNDSTICKS4全新一代无线水晶蓝牙音箱评测...
  5. 客制化键盘键位修改_IQUNIX Slim87 RGB机械键盘评测
  6. 微服务面试必问的Dubbo,这么详细还怕自己找不到工作?
  7. 为什么蚂蚁金服架构师建议从Zookeeper开始提升技术水平?
  8. springMVC整合swagger(亲自试验完全可用)
  9. 【JEECG 官方】技术支持联系方式
  10. 专刊文章 - Web UI框架引领J2EE新开发模式(代码生成器+手工merge半智能开发)