大白书中无向图的点双联通分量(BCC)模板的分析与理解
对于一个无向图,如果任意两点至少存在两条点不重复(除起点和终点外无公共点)的路径,则这个图就是点双联通。
这个要求等价于任意两条边都存在于一个简单环(即同一个点不能在圈中出现两次)中,即内部无割点。
那么算法首先要求出割点。
从代码中可以看出:只要求出割点,就开始组一个bcc中。
如果割点两侧都不存在环的话会怎么处理呢?
代码中相邻的割点(或者是割点和根节点)也被当做一个bcc处理。
bccno[i]为点i所在的bcc序号,那么割点的bccno为多少呢?
割点的bccno没有意义,割点存在于多个bcc中。
割点:删除这个点后,联通分量增加,那么这个点就是割点。
在图的dfs搜索树中,非根节点u的子节点v没有方向边(dfs搜索树中后代指向祖先的边)返回u的祖先,那么u就是割点。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#include<stack>
#include<vector>
using namespace std;
const int MAXN=1e3+,INF=0x3f3f3f3f,MOD=1e9+;
int n;
int vis[MAXN][MAXN];
vector<int>G[MAXN];
int dfs_color=; ///dfs时间戳
int pre[MAXN],post[MAXN];
int bcc_cnt=; ///联通分量
int low[MAXN]; ///u及其后代所能连回的最早祖先的pre值
int iscut[MAXN]; ///割点
vector<pair<int,int> >birdge; ///桥
struct edge
{
int u,v;
};
stack<edge>S;
int bccno[MAXN]; ///点所在的双联通分量
vector<int>bcc[MAXN]; ///双联通分量
int dfs(int u,int fa)
{
int lowu=pre[u]=++dfs_color;
int child=;
for(int i=; i<G[u].size(); i++)
{
int v=G[u][i];
edge e=(edge)
{
u,v
};
if(!pre[v])
{
S.push(e);
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>=pre[u])
{
iscut[u]=true;
if(lowv>pre[u]) birdge.push_back(make_pair(u,v));
bcc_cnt++;
bcc[bcc_cnt].clear();
while(!S.empty())
{
edge x=S.top();
S.pop();
if(bccno[x.u]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(x.u);
bccno[x.u]=bcc_cnt;
}
if(bccno[x.v]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(x.v);
bccno[x.v]=bcc_cnt;
}
if(x.u==u&&x.v==v) break;
}
}
}
else if(pre[v]<pre[u]&&v!=fa)
{
S.push(e);
lowu=min(lowu,pre[v]);
}
}
if(fa<&&child==) iscut[u]=;
low[u]=lowu;
return low[u];
}
void find_bcc()
{
bcc_cnt=;
dfs_color=;
memset(pre,,sizeof(pre));
memset(iscut,,sizeof(iscut));
memset(bccno,,sizeof(bccno));
for(int i=; i<=n; i++)
if(!pre[i]) dfs(i,-);
}
void init(int m)
{
memset(vis,,sizeof(vis));
for(int i=; i<=n; i++) G[i].clear();
birdge.clear();
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
}
int main()
{
int m;
while(scanf("%d%d",&n,&m))
{
init(m);
find_bcc();
for(int i=; i<=bcc_cnt; i++)
{
cout<<i<<":";
for(int j=; j<bcc[i].size(); j++)
cout<<bcc[i][j]<<" ";
cout<<endl;
}
}
return ;
}
大白书中无向图的点双联通分量(BCC)模板的分析与理解的更多相关文章
- 无向图边双联通分量 tarjan 模板
#include <bits/stdc++.h> using namespace std; const int MAXN = 100005; const int MAXM = 500005 ...
- 点双联通分量(BCC)的正确姿势
Tarjan求点双连通分量 - 李昊哲
- Spoj 2878 KNIGHTS - Knights of the Round Table | 双联通分量 二分图判定
题目链接 考虑建立原图的补图,即如果两个骑士不互相憎恨,就在他们之间连一条无向边. 显而易见的是,如果若干个骑士在同一个点数为奇数的环上时,他们就可以在一起开会.换句话说,如果一个骑士被一个奇环包含, ...
- 『Tarjan算法 无向图的双联通分量』
无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...
- 图连通性【tarjan点双连通分量、边双联通分量】【无向图】
根据 李煜东大牛:图连通性若干拓展问题探讨 ppt学习. 有割点不一定有割边,有割边不一定有割点. 理解low[u]的定义很重要. 1.无向图求割点.点双联通分量: 如果对一条边(x,y),如果low ...
- 【UVA10972】RevolC FaeLoN (求边双联通分量)
题意: 给你一个无向图,要求把所有无向边改成有向边,并且添加最少的有向边,使得新的有向图强联通. 分析: 这题的解法还是很好想的.先用边双联通分量缩点,然后找新图中入度为0和为1的点,入度为0则ans ...
- HDU5409---CRB and Graph 2015多校 双联通分量缩点
题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的. 不存在输出0 0 首先 若删除某一条边后存在多个联通分 ...
- Tarjan总结(缩点+割点(边)+双联通+LCA+相关模板)
Tarjan求强连通分量 先来一波定义 强连通:有向图中A点可以到达B点,B点可以到达A点,则称为强连通 强连通分量:有向图的一个子图中,任意两个点可以相互到达,则称当前子图为图的强连通分量 强连通图 ...
- Tarjan 强连通分量 及 双联通分量(求割点,割边)
Tarjan 强连通分量 及 双联通分量(求割点,割边) 众所周知,Tarjan的三大算法分别为 (1) 有向图的强联通分量 (2) 无向图的双联通分量(求割点,桥) ...
随机推荐
- oracle增加记录谁在连接你的数据库
我们都知道在v$session 中记录着客户端的机器名称,但是没有IP , 如果记录clinet ip 呢? 有两种思路: ① 利用trigger,后面就是这种方式 ② 利用 DBMS_S ...
- thinkphp5.1 判断是不是post提交
if(Request::isPost()){ }else{ } 这样就对了
- JetBrains 产品线破解方法
参考: 1.https://www.jianshu.com/p/f404994e2843 2.https://xclient.info/s/intellij-idea.html#versions 3. ...
- python3集合练习(set)
#集合是由不同元素组成;无序;集合中的元素必须是不可变类型;#s = {} 或者 s = set() 创建集合#update()扩展集合.返回值为Noneg1 = {'wcj','good','luc ...
- js:苹果手机页面返回,数据不刷新问题
$(function () { var isPageHide = false; window.addEventListener('pageshow', function () { ...
- 浅谈Java堆内存分代回收
目录 1.概述 2.堆内存是如何分代的 3.各分代之间是如何配合工作的 1.概述 与C++不同的是, 在Java中我们无需关心对象占用空间的释放, 这主要得益于Java中的垃圾处理器(简称GC)帮助我 ...
- React-Native: bios打开VT-x选项
问题: 我在Android Studio新建一个虚拟机的时候出现如图错误: 解决方案:重启电脑,开机的时候不停的按f12(不同的主机不一样),进入bios,然后打开Virtualization Tec ...
- findbugs插件使用
本文以idea的插件举例子 介绍 Findbugs是一个静态分析工具,它检查类或者JAR 文件,将字节码与一组缺陷模式进行对比以发现可能的问题. idea安装 自此,插件安装完毕,需要重启idea才生 ...
- 如何查看和清除svn登录信息
切换svn登录用 点击clear,出现用户信息,勾选后点击ok 即清除 .下次访问svn需要重新登录
- Linux samba多用户挂载
samba 多用户挂载 通过multiuser挂载选项,使用基于密码验证和cifscreds实现访问控制在默认情况下,samba共享挂载后,是通过挂载时的验证来实现对挂载资源的访问控制.通过新的mul ...