【割点】【割边】tarjan
洛谷割点模板题——传送门

割边:在连通图中,删除了连通图的某条边后,图不再连通。这样的边被称为割边,也叫做桥。
割点:在连通图中,删除了连通图的某个点以及与这个点相连的边后,图不再连通。这样的点被称为割点。
DFS搜索树:用DFS对图进行遍历时,按照遍历次序的不同,我们可以得到一棵DFS搜索树。

树边:在搜索树中的蓝色线所示,可理解为在DFS过程中访问未访问节点时所经过的边,也称为父子边
回边:在搜索树中的橙色线所示,可理解为在DFS过程中遇到已访问节点时所经过的边,也称为返祖边、后向边
观察DFS搜索树,我们可以发现有两类节点可以成为割点。对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;对非叶子节点u(非根节点),若其中的某棵子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与该棵子树的节点不再连通;则节点u为割点。对于根结点,显然很好处理;但是对于非叶子节点,怎么去判断有没有回边是一个值得深思的问题。我们用dfn[u]记录节点u在DFS过程中被遍历到的次序号,low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小),那么low[u]的计算过程如下。

对于给的例子,其求出的dfn和low数组如下。
id 1 2 3 4 5 6
dfn 1 2 3 4 5 6
low 1 1 1 4 4 4
可以发现,对于情况2,当(u,v)为树边且low[v]≥dfn[u]时,节点u才为割点。而当(u,v)为树边且low[v]>dfn[u]时,表示v节点只能通过该边(u,v)与u连通,那么(u,v)即为割边。tarjan算法的时间复杂度是O(n+m)的,非常快。
——附带码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm> using namespace std; const int maxn = ;
int n, m, cnt, rp;
int next[ * maxn], to[ * maxn], head[maxn], low[maxn], dfn[maxn], father[maxn];//father为父节点
vector <int> cut_point;
vector < pair <int, int> > cut_edge; void add(int x, int y)
{
to[cnt] = y;
next[cnt] = head[x];
head[x] = cnt++;
} void tarjan(int u)
{
int i, v, child = ;//child表示当前节点孩子数量
bool flag = ;
dfn[u] = low[u] = ++rp;
for(i = head[u]; i != -; i = next[i])
{
v = to[i];
if(!dfn[v])
{
child++;
father[v] = u;
tarjan(v);
if(low[v] >= dfn[u]) flag = ;//割点
if(low[v] > dfn[u]) cut_edge.push_back(make_pair(min(u, v), max(u, v)));//割边
low[u] = min(low[u], low[v]);
}
else if(v != father[u]) low[u] = min(low[u], dfn[v]); }
//根节点若有两棵或两棵以上的子树则该为割点
//非根节点若所有子树节点均没有指向u的祖先节点的回边则为割点
if((father[u] == && child > ) || (father[u] && flag)) cut_point.push_back(u);
} int main()
{
int i, j, x, y, s;
memset(head, -, sizeof(head));
scanf("%d %d", &n, &m);
for(i = ; i <= m; i++)
{
scanf("%d %d", &x, &y);
add(x, y);
add(y, x);
}
for(i = ; i <= n; i++)//图可能不联通(mdzz的洛谷模板题)
if(!dfn[i])
tarjan(i);
sort(cut_point.begin(), cut_point.end());
s = cut_point.size();
printf("%d\n", s);
for(i = ; i < s; i++) printf("%d ", cut_point[i]);//输出割点
s = cut_edge.size();
printf("\n%d\n", s);
for(i = ; i < s; i++) printf("%d %d\n", cut_edge[i].first, cut_edge[i].second);//输出割边
return ;
}
经过培训,发现上面的代码如果有重边就会拉闸。
下面是可以应对重边的代码
# include <iostream>
# include <cstdio>
# include <cstring>
# include <string>
# include <cmath>
# include <vector>
# include <map>
# include <queue>
# include <cstdlib>
# define MAXN
using namespace std; inline void File() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
#else
//freopen();
//freopen();
#endif
} inline int get_num() {
int k = , f = ;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -;
for(; isdigit(c); c = getchar()) k = k * + c - '';
return k * f;
} int n, m, tim, cnt;
int dfn[MAXN], low[MAXN], f[MAXN], to[MAXN], next[MAXN], head[MAXN];
vector <int> cut_point;
vector < pair <int, int> > cut_edge; inline void add(int x, int y)
{
to[cnt] = y;
next[cnt] = head[x];
head[x] = cnt++;
} inline void dfs(int u, int fa)
{
int i, v, child = ;
bool flag = ;
dfn[u] = low[u] = ++tim;
for(i = head[u]; i != -; i = next[i])
{
if((i ^ ) == fa) continue;
v = to[i];
if(!dfn[v])
{
child++;
f[v] = u;
dfs(v, i);
if(low[v] >= dfn[u]) flag = ;
if(low[v] > dfn[u]) cut_edge.push_back(make_pair(min(u, v), max(u, v)));
low[u] = min(low[v], low[u]);
}
else low[u] = min(low[u], dfn[v]);
}
if((!f[u] && child > ) || (f[u] && flag)) cut_point.push_back(u);
} int main()
{
int i, j, x, y;
n = get_num();
m = get_num();
memset(head, -, sizeof(head));
for(i = ; i <= m; i++)
{
x = get_num();
y = get_num();
add(x, y);
add(y, x);
}
for(i = ; i <= n; i++)
if(!dfn[i])
dfs(i, -);
for(i = ; i < cut_point.size(); i++) printf("%d\n", cut_point[i]);
puts("");
for(i = ; i < cut_edge.size(); i++) printf("%d %d\n", cut_edge[i].first, cut_edge[i].second);
puts("");
return ;
}
【割点】【割边】tarjan的更多相关文章
- 求割点 割边 Tarjan
附上一般讲得不错的博客 https://blog.csdn.net/lw277232240/article/details/73251092 https://www.cnblogs.com/colle ...
- tarjan 割点 割边
by GeneralLiu tarjan 求 割点 割边 无向图 的 割点 割边: 对于无向连通图来说, 如果删除 一个点以及与它相连的边 之后, 使得这个图不连通, 那么该点为割点 : ...
- Tarjan算法 (强联通分量 割点 割边)
变量解释: low 指当前节点在同一强连通分量(或环)能回溯到的dfn最小的节点 dfn 指当前节点是第几个被搜到的节点(时间戳) sta 栈 vis 是否在栈中 ans 指强连通分量的数量 top ...
- hihoCoder 1183 连通性一·割边与割点(Tarjan求割点与割边)
#1183 : 连通性一·割边与割点 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 还记得上次小Hi和小Ho学校被黑客攻击的事情么,那一次攻击最后造成了学校网络数据的丢 ...
- 【学习整理】Tarjan:强连通分量+割点+割边
Tarjan求强连通分量 在一个有向图中,如果某两点间都有互相到达的路径,那么称中两个点强联通,如果任意两点都强联通,那么称这个图为强联通图:一个有向图的极大强联通子图称为强联通分量. 算法可以在 ...
- tarjan算法(割点/割边/点连通分量/边连通分量/强连通分量)
tarjan算法是在dfs生成一颗dfs树的时候按照访问顺序的先后,为每个结点分配一个时间戳,然后再用low[u]表示结点能访问到的最小时间戳 以上的各种应用都是在此拓展而来的. 割点:如果一个图去掉 ...
- tarjan模板 强联通分量+割点+割边
// https://www.cnblogs.com/stxy-ferryman/p/7779347.html ; struct EDGE { int to, nt; }e[N*N]; int hea ...
- Tarjan算法与割点割边
目录 Tarjan算法与无向图的连通性 1:基础概念 2:Tarjan判断割点 3:Tarjan判断割边 Tarjan算法与无向图的连通性 1:基础概念 在说Tarjan算法求解无向图的连通性之前,先 ...
- tarjan求割点割边的思考
这个文章的思路是按照这里来的.这里讨论的都是无向图.应该有向图也差不多. 1.如何求割点 首先来看求割点.割点必须满足去掉其以后,图被分割.tarjan算法考虑了两个: 根节点如果有两颗及以上子树,它 ...
- Tarjan 割点割边【模板】
#include <algorithm> #include <cstring> #include <cstdio> using namespace std; +); ...
随机推荐
- Python字典详解
转载请注明出处 Python字典(dict)是一个很常用的复合类型,其它常用符合类型有:数组(array).元组(touple)和集合(set).字典是一个key/value的集合,key可以是任意可 ...
- MySQL学习分享-->日期时间类型
日期时间类型 ①如果要用来表示年月日时分秒,一般使用datetime类型: ②如果要用来表示年月日,一般使用date类型: ③如果要表示时分秒,一般使用time类型: ④如果只是表示年份,一般使用ye ...
- 移动端利用rem实现自适应布局
好久没有写博客了,刚好说说最近遇到的移动端布局问题吧. 本来一直是觉得我的页面布局能力还是不错的,当然,是相对于较基础的来说还是不错的.不过,自己写的案例终归是跟实际开发有区别的,自己写案例的是觉得这 ...
- Python开发【第十八篇】Web框架之Django【基础篇】
一.简介 Python下有许多款不同的 Web 框架,Django 是重量级选手中最有代表性的一位,许多成功的网站和APP都基于 Django. Django 是一个开放源代码的Web应用框架,由 P ...
- 一个很逗的东西——Jd
这个嘛是本人专门为了NOI上面对拍程序写的对拍程序,已经经历了NOI2015的考验:更重要的是——纯Pascal的哦(HansBug:其实是我不会写.sh脚本TT,谁叫用惯了windows的我只会写b ...
- 3377: [Usaco2004 Open]The Cow Lineup 奶牛序列
3377: [Usaco2004 Open]The Cow Lineup 奶牛序列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 16 Solved ...
- 2017-3-18 SQL server 数据库 45道题
use data02161212 create table student (Sno nvarchar(3) primary key, Sname nvarchar(8) not null, Ssex ...
- JVM中GC浅解:垃圾回收的了解
1.为什么要有GC 没有GC的世界,我们需要手动进行内存管理,但是内存管理是纯技术活,又容易出错.但是我们写码的目的是为了解决业务问题,所以可以把这种纯技术活自动化,当然自动化也是有代价的. 2.垃圾 ...
- Windows 10 IoT Serials 7 – 如何用树莓派制作家庭流媒体播放器
Windows 10平台引入了AllJoyn开源软件框架,它提供了一组服务可以创建动态近端网络,让设备可以相互连接实现功能交互.目前,AllJoyn开源软件框架由AllSeen联盟负责管理.AllSe ...
- JAVA源码剖析(容器篇)HashMap解析(JDK7)
Map集合: HashMap底层结构示意图: HashMap是一个“链表散列”,其底层是一个数组,数组里面的每一项都是一条单链表. 数组和链表中每一项存的都是一“Entry对象”,该对象内部拥有key ...