tarjan无向图割点与割边板子
\(\Huge{割点}\)
- \(无向图割点判定法则\)
当遍历到一个点x时,这个点为割点的情况有两种:- 第一种是该节点为根节点且子节点数>=2,必导致两个子节点不连通;
- 第二种是该节点不为根节点,且 \(low[i]>=dfn[x]\),即子节点i可回溯到的最早的点不早于x点,那么删去x一定导致x的子节点不连通;
- 反之,若 \(low[i]<dfn[x]\),则说明i能绕行到比x更早的点,则x不是割点;(即环内的点割不掉);

//无向图割点模板
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define N 20001
using namespace std;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool f=1;
register char c=getchar();
for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=0;
for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
x=(f?x:~x+1);
}
int n,m,a,b,tot,root,ans,dfn[N],low[N];
bool cut[N];
vector<int> e[N];
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
int child=0;
for(int y:e[x])
if(!dfn[y])
{
tarjan(y),
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
child++;
if(x!=root||child>1) cut[x]=1;
}
}
else low[x]=min(low[x],dfn[y]);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(n),read(m);
while(m--)
read(a),read(b),
e[a].push_back(b),
e[b].push_back(a);
for(root=1;root<=n;root++)
if(!dfn[root]) tarjan(root);
for(int i=1;i<=n;i++) if(cut[i]) ans++;
cout<<ans<<endl;
for(int i=1;i<=n;i++) if(cut[i]) cout<<i<<' ';
}
- 样例输入:
7 10
1 2
2 3
3 4
2 4
1 4
1 5
5 6
5 8
7 8
5 7 - 样例输出
2
1 5

\(\Huge{割边}\)
- \(无向图的割边判定法则\)
- 在遍历到一个点x 的子节点y,满足 \(low[y]>dfn[x]\),则 \((x,y)\) 这条边就是割边;
- \(low[y]>dfn[x]\) ,说明不经过 \((x,y)\) ,y无法到达比x更早的点,故割掉这条边;
- 反之,若 \(low[y]<=dfn[x]\),则y能够到达x或比x更早的点,\((x,y)\) 就不是割边,即环内没有割边;
- \(注意事项:\)
- 求桥的时候,议案为边是无向的,所以父亲与孩子的关系也要自己规定一下,正常的 $ else low[x]=min(low[x],low[y])$ 应改为 $ else if(y!=fa) low[x]=min(low[x],low[y])$;因为如果y是x的父亲,这条无向边就被误认为是环了;
- 找桥的时候,有重边的一定不是桥;


割边是(1,2)和(1,5)。
- 板子:洛谷 P1656 炸铁路
- 题目描述
A国要使B国的铁路系统瘫痪,要炸毁一条铁路使其铁路无法全部联通,问可炸毁那一条铁路? - 输入格式
第一行 \(n,m\) (\(1<=n<=150,1<=m<=5000\)),分别表示n个城市和m条铁路。
以下m行,每行 \(a,b\) ,表示城市a和城市b间有铁路直接联通。 - 输出格式
输出若干行,每行 \(a,b\) ,其中 \(a<b\) ,表示\((a,b)\)是 \(key road\) .
请注意:输出时,所有的数对必须按照a从小到大排序输出,若a相同,根据b从小到大输出。 - 代码实现:
//无向图割边模板,炸铁路
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define N 200
#define M 20001
using namespace std;
template<typename Tp> inline void read(Tp&x)
{
x=0;register bool f=1;
register char c=getchar();
for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=0;
for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
x=(f?x:~x+1);
}
int n,m,a,b,tot,ans,dfn[N],low[N];
bool v[N][N],again[N][N];
vector<int> e[M];
struct aa{int l,r;}s[M];
bool cmp(aa s1,aa s2){if(s1.l==s2.l) return s1.r<s2.r;return s1.l<s2.l;}
void tarjan(int x,int fa)
{
dfn[x]=low[x]=++tot;
for(int y:e[x])
if(!dfn[y])
{
tarjan(y,x),
low[x]=min(low[x],low[y]);
if(low[y]>dfn[x]) s[++ans]=(aa){x,y};
}
else if(y!=fa||again[x][y]) low[x]=min(low[x],dfn[y]);//重边一定不是割边
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(n),read(m);
while(m--)
{
read(a),read(b);
if(v[a][b])
{
again[a][b]=again[b][a]=1;//判断重边
continue;
}
v[a][b]=v[b][a]=1,
e[a].push_back(b),
e[b].push_back(a);
}
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,i);
stable_sort(s+1,s+1+ans,cmp);
for(int i=1;i<=ans;i++) cout<<s[i].l<<' '<<s[i].r<<endl;
}
- 样例输入
7 10
1 2
2 3
2 4
3 4
1 5
5 6
5 7
7 8
5 8
6 5 - 样例输出
1 2
1 5

tarjan无向图割点与割边板子的更多相关文章
- 图论分支-Tarjan初步-割点和割边
所谓割点(顶)割边,我们引进一个概念 割点:删掉它之后(删掉所有跟它相连的边),图必然会分裂成两个或两个以上的子图. 割边(桥):删掉一条边后,图必然会分裂成两个或两个以上的子图,又称桥. 这样大家就 ...
- tarjan求割点与割边
tarjan求割点与割边 洛谷P3388 [模板]割点(割顶) 割点 解题思路: 求割点和割点数量模版,对于(u,v)如果low[v]>=dfn[u]那么u为割点,特判根结点,若根结点子树有超过 ...
- hihoCoder 1183 连通性一·割边与割点(Tarjan求割点与割边)
#1183 : 连通性一·割边与割点 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 还记得上次小Hi和小Ho学校被黑客攻击的事情么,那一次攻击最后造成了学校网络数据的丢 ...
- Tarjan在图论中的应用(二)——用Tarjan来求割点与割边
前言:\(Tarjan\) 求割点和割边建立在 \(Tarjan\)算法的基础之上,因此建议在看这篇博客之前先去学一学\(Tarjan\). 回顾\(Tarjan\)中各个数组的定义 首先,我们来回顾 ...
- 『Tarjan算法 无向图的割点与割边』
无向图的割点与割边 定义:给定无相连通图\(G=(V,E)\) 若对于\(x \in V\),从图中删去节点\(x\)以及所有与\(x\)关联的边后,\(G\)分裂为两个或以上不连通的子图,则称\(x ...
- Tarjan无向图的割点和桥(割边)全网详解&算法笔记&通俗易懂
更好的阅读体验&惊喜&原文链接 感谢@yxc的腿部挂件 大佬,指出本文不够严谨的地方,万分感谢! Tarjan无向图的割点和桥(割边) 导言 在掌握这个算法前,咱们有几个先决条件. [ ...
- Tarjan 强连通分量 及 双联通分量(求割点,割边)
Tarjan 强连通分量 及 双联通分量(求割点,割边) 众所周知,Tarjan的三大算法分别为 (1) 有向图的强联通分量 (2) 无向图的双联通分量(求割点,桥) ...
- Tarjan 算法求割点、 割边、 强联通分量
Tarjan算法是一个基于dfs的搜索算法, 可以在O(N+M)的复杂度内求出图的割点.割边和强联通分量等信息. https://www.cnblogs.com/shadowland/p/587225 ...
- tarjan求割点割边的思考
这个文章的思路是按照这里来的.这里讨论的都是无向图.应该有向图也差不多. 1.如何求割点 首先来看求割点.割点必须满足去掉其以后,图被分割.tarjan算法考虑了两个: 根节点如果有两颗及以上子树,它 ...
- POJ1144 tarjan+网络中割点与割边的数量
题目链接:http://poj.org/problem?id=1144 割点与割边的数量我们可以通过tarjan的思想从一个点开始对其余点进行访问.访问的顺序构成一棵dfs树,其中根节点到任何一个结点 ...
随机推荐
- SQL注入简介
SQL注入(SQL Injection)是一种计算机安全漏洞,它允许攻击者通过操纵应用程序的输入来执行恶意的SQL查询,从而访问.修改或删除数据库中的数据.这种攻击通常发生在应用程序未正确验证.过滤或 ...
- Linux虚拟机安装及下载
centos 7操作系统下载及安装步骤 (仅供参考) 下载: 1.打开如下网站:先下载镜像文件 ping:https://www.centos.org/download/ 2.进入到如下界面 3.然后 ...
- MySQL系列之备份恢复——运维在备份恢复方面、备份类型、备份方式及工具、逻辑备份和物理备份、备份策略、备份工具使用-mysqldump、企业故障恢复案例、备份时优化参数、MySQL物理备份工具
文章目录 1. 运维在数据库备份恢复方面的职责 1.1 设计备份策略 1.2 日常备份检查 1.3 定期恢复演练(测试库) 1.4 故障恢复 1.5 迁移 2. 备份类型 2.1 热备 2.2 温备 ...
- Oracle:字符串的拼接、截取、查找、替换
一.拼接:1.使用"||"来拼接字符串: select '拼接'||'字符串' as Str from dual; 2.使用concat(param1,param2)函数实现: s ...
- PostgreSQL快速导入千万条数据
目录 一.测试环境 二.修改源数据为COPY可用的格式 三.DDL 四.COPY 五.结论 为了与MySQL做个对比,做一个PG的数据导入测试,使用COPY方式,测试环境保持一致,具体如下所述. 一. ...
- 2023_10_09_MYSQL_DAY_01_笔记
2023_10_09_MYSQL_DAY_01 #运算符的优先级 SELECT ename, job, sal FROM emp WHERE ( job='SALESMAN' OR job='PRES ...
- 为什么 CSS flex 布局中没有 `justify-items` 和 `justify-self`?
为什么 CSS flex 布局中没有 justify-items 和 justify-self? 为什么在 CSS flex 布局中存在 align-items 和 align-self,却没有 ju ...
- H5-geolocation学习
geolocation--定位 PC--IP地址 精度比较低 IP库 Chrome -> Google 手机--GPS window.navigator.geolocation 单次 getCu ...
- 未能添加SSL证书,错误1312
1.win+r打开运行,输入mmc 2.在控制台1[控制台根节点]->文件->添加/删除....->选择证书->添加-选择计算机账户->完成->确认 3.找到证书文 ...
- flask 三方模块
flask 三方插件 Flask-AppBuilder - Simple and rapid Application builder, includes detailed security, auto ...