一.基本概念

1.桥:若无向连通图的边割集中只有一条边,则称这条边为割边或者桥 (离散书上给出的定义。。

通俗的来说就是无向连通图中的某条边,删除后得到的新图联通分支至少为2(即不连通;

2.割点:若无向连通图的点割集中只有一个点,则称这个点为割点或者关节点 ;

通俗的来说就是无向连通图中的某条边,删除后得到的新图连通分支至少为2;

二:tarjan算法求割点和桥

1.割点:1)当前节点为树根的时候,条件是“要有多余一棵子树”;

         如果这有一颗子树,去掉这个点也没有影响,如果有两颗子树,去掉这点,两颗子树就不连通了;

2)当前节点u不是树根的时候,条件是“low[v]>=dfn[u]”,也就是在u之后遍历的点,能够向上翻,

      最多到u,如果能翻到u的上方,那就有环了,去掉u之后,图仍然连通。

2.桥:若一条无向边(u,v)是桥,

1)当且仅当无向边(u,v)是树枝边,需要满足dfn(u)<low(v),即v向上翻不到u及其以上的点,

      那么u--v之间一定能够有1条或者多条边不能删去, 因为他们之间有部分无环,是桥,

      如果v能上翻到u那么u--v就是一个环,删除其中一条路径后,仍然是连通的。

3.注意点:1)求桥的时候:因为边是无方向的,所以父亲孩子节点的关系需要自己规定一下,

在tarjan的过程中if(v不是u的父节点) low[u]=min(low[u],dfn[v]);

因为如果v是u的父亲,那么这条无向边就被误认为是环了。

2)找桥的时候:注意看看有没有重边,有重边的边一定不是桥,也要避免误判。

4.也可以先进行tarjan(),求出每一个点的dfn和low,并记录dfs过程中的每个点的父节点,

    遍历所有点的low,dfn来寻找桥和割点

代码:

 #include <iostream>
#include <stdio.h>
#include <vector>
#include <string.h>
using namespace std; const int MAXN=1e5+;
vector<int> mp[MAXN];
bool is_cut[MAXN];
int n, m, count=;
int low[MAXN], dfn[MAXN], pre[MAXN];//pre[u]记录u的父亲节点编号
//dfn[u]记录节点u在DFS过程中被遍历到的次序号,low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小 void tarjan(int u, int fu){
pre[u]=fu;//记录当前u的父亲节点
dfn[u]=low[u]=count++;
for(int i=; i<mp[u].size(); i++){
int v=mp[u][i];
if(dfn[v]==-){
tarjan(v, u);
low[u]=min(low[u], low[v]);
}else if(fu!=v){//如果v是u的父亲的话,即有重边,那么不可能是桥
low[u]=min(low[u], dfn[v]);
}
}
} void solve(void){
int rootson=;
tarjan(, );
for(int i=; i<=n; i++){
int v=pre[i];
if(v==){
rootson++;//统计根节点的子树个数,若其不小于2,即为割点
}else if(low[i]>=dfn[v]){
is_cut[v]=true;
}
}
if(rootson>) is_cut[]=true;
puts("割点为:");
for(int i=; i<=n; i++){//输出割点
if(is_cut[i]){
printf("%d ", i);
}
}
puts("\n桥为:");
for(int i=; i<=n; i++){
int v=pre[i];
if(v>&&low[i]>dfn[v]){
printf("%d %d\n", v, i);
}
}
puts("");
} int main(void){
scanf("%d%d", &n, &m);
for(int i=; i<m; i++){
int x, y;
scanf("%d%d", &x, &y);
mp[x].push_back(y);
mp[y].push_back(x);
}
memset(dfn, -, sizeof(dfn));
memset(low, -, sizeof(low));
solve();
return ;
}

求桥的另一种写法(更快一点):

 #include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std; const int MAXN = 1e5 + ; struct node{
int v, next, use;
}edge[MAXN << ]; bool bridge[MAXN];
int low[MAXN], dfn[MAXN], vis[MAXN];
int head[MAXN], pre[MAXN], ip, sol, count; void init(void){
memset(head, -, sizeof(head));
memset(vis, false, sizeof(vis));
memset(bridge, false, sizeof(bridge));
count = sol = ip = ;
} void addedge(int u, int v){
edge[ip].v = v;
edge[ip].use = ;
edge[ip].next = head[u];
head[u] = ip++;
} void tarjan(int u){
vis[u] = ;
dfn[u] = low[u] = count++;
for(int i = head[u]; i != -; i = edge[i].next){
if(!edge[i].use){
edge[i].use = edge[i ^ ].use = ;
int v = edge[i].v;
if(!vis[v]){
pre[v] = u;
tarjan(v);
low[u] = min(low[u], low[v]);
if(dfn[u] < low[v]){
sol++;
bridge[v] = true;
}
}else if(vis[v] == ){
low[u] = min(low[u], dfn[v]);
}
}
}
vis[u] = ;
} int main(void){
int n, m, q, x, y, cas = ;
while(~scanf("%d%d", &n, &m)){
if(!n && !m) break;
init();
for(int i = ; i < m; i++){
scanf("%d%d", &x, &y);
addedge(x, y);
addedge(y, x);
}
pre[] = ;
tarjan();
for(int i = ; i <= n; i++){
if(bridge[i]) cout << i << " " << pre[i] << endl;
}
}
return ;
}

以上参考博客:http://www.cnblogs.com/c1299401227/p/5402747.html

求无向图的割点和桥模板(tarjan)的更多相关文章

  1. 求 无向图的割点和桥,Tarjan模板

    /* 求 无向图的割点和桥 可以找出割点和桥,求删掉每个点后增加的连通块. 需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重 */ const int MAXN = 10010; cons ...

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

    一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不连通,则称该边为桥. 2.割点:无向连通图中 ...

  3. Tarjan无向图的割点和桥(割边)全网详解&算法笔记&通俗易懂

    更好的阅读体验&惊喜&原文链接 感谢@yxc的腿部挂件 大佬,指出本文不够严谨的地方,万分感谢! Tarjan无向图的割点和桥(割边) 导言 在掌握这个算法前,咱们有几个先决条件. [ ...

  4. 无向图的割点和桥 tarjan 模板

    #include <bits/stdc++.h> using namespace std; const int MAXN = 20005; const int MAXM = 100005; ...

  5. tarjan算法--求解无向图的割点和桥

    1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥 也就是说 无向连通图中,如果删除某边后,图变成不连通,则称该边为桥 2.割点:无向连通图中,如 ...

  6. 【关节点+桥】关节点和桥模板 Tarjan

    #include <cstdio> #include <cstring> #include <algorithm> using namespace std; con ...

  7. Tarjan求无向图割点、桥详解

    tarjan算法--求无向图的割点和桥   一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不 ...

  8. [Tarjan系列] Tarjan算法求无向图的双连通分量

    这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...

  9. [Tarjan系列] Tarjan算法求无向图的桥和割点

    RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...

随机推荐

  1. EasyDarwin EasyClient开源流媒体播放器,支持多窗口显示

    EasyDarwin开源团队开源的EasyClient客户端将支持流媒体采集.编码.推送.播放.抓图.录像.Onvif 等全套功能(大家持续关注我们Github的commit),其中播放功能是开源流媒 ...

  2. javaweb开发之javaBean

    一.JavaBean简介 JavaBean是使用Java语言开发的一个可重用的组件,在JSP的开发中可以使用JavaBean减少重复代码,使整个JSP代码的开发更简洁.JSP搭配JavaBean来使用 ...

  3. Splits a tensor into sub tensors

    https://www.tensorflow.org/api_docs/python/tf/split # 'value' is a tensor with shape [5, 30] # Split ...

  4. Django中如何实现数据库路由?

    虽然我们提供了数据库的信息,它知道怎么连接数据库,但问题是我们保存里面有很多模型,它不知道哪个模型存到哪个数据库.这就要求我们自己来指定,也就是我们自己来实现一个数据库路由.一个数据库路由是一个拥有4 ...

  5. [IR课程笔记]统计语言模型

    Basic idea 1.一个文档(document)只有一个主题(topic) 2.主题指的是这个主题下文档中词语是如何出现的 3.在某一主题下文档中经常出现的词语,这个词语在这个主题中也是经常出现 ...

  6. [noip2014day1-T2]联合权值

    无向连通图 G 有 n 个点,n-1 条边.点从 1 到 n 依次编号,编号为 i 的点的权值为 Wi,每条边的长度均为 1.图上两点(u, v)的距离定义为 u 点到 v 点的最短距离.对于图 G ...

  7. 网页中的title中设置图标

    每个网页中title旁边的图标是怎么实现的呢?像这个百度的图标,今天做了一下,很简单,下面记录一下. 做一个图片,一般的图标都可以,把图标后缀改为.ico格式就OK了,放在项目路径下,保证该图片可以被 ...

  8. LightOJ1336 Sigma Function —— 质因子分解、约数和为偶数

    题目链接:https://vjudge.net/problem/LightOJ-1336 1336 - Sigma Function    PDF (English) Statistics Forum ...

  9. HDU4372 Count the Buildings —— 组合数 + 第一类斯特林数

    题目链接:https://vjudge.net/problem/HDU-4372 Count the Buildings Time Limit: 2000/1000 MS (Java/Others)  ...

  10. HDU4045 Machine scheduling —— 隔板法 + 第二类斯特林数

    题目链接:https://vjudge.net/problem/HDU-4045 Machine scheduling Time Limit: 5000/2000 MS (Java/Others)   ...