求割点 割边 Tarjan
附上一般讲得不错的博客 https://blog.csdn.net/lw277232240/article/details/73251092
https://www.cnblogs.com/collectionne/p/6847240.html
https://blog.csdn.net/zhn_666/article/details/77971619
然后附上模板题: https://vjudge.net/problem/HihoCoder-1183
裸题,直接要你输出割点 和 割边.. 唯一坑点就是割边的输出..自己看题.
#include <set>
#include <cstdio>
#include <algorithm> using namespace std; struct Point {
int u;
int v;
Point () { }
Point (int uu, int vv) : u(uu), v(vv) { }
bool operator < (const Point &a) const {
if (u != a.u) return u < a.u;
return v < a.v;
}
}; struct Edge {
int lst;
int to;
}edge[];
int head[];
int qsz = ; inline void add(int u, int v) {
edge[qsz].lst = head[u];
edge[qsz].to = v;
head[u] = qsz++;
} int dfn[];
int low[];
//int pa[20500];
int dfn_num;
set<int> ans;
set<Point> ans_pt;
/*
void Tarjan(int u) {
int i, v, child = 0;
dfn[u] = low[u] = ++dfn_num;
for (i=head[u]; i; i=edge[i].lst) {
v = edge[i].to;
if (v == pa[u]) continue;
if (!dfn[v]) { // 树边, 父子边
pa[v] = u;
Tarjan(v);
child++;
low[u] = min(low[u], low[v]);
// case 1 u是根节点,同时只是有2颗子树---> 无向图 所以可能有多个根节点.
if (!pa[u] && child>=2) ans.insert(u) ; // 根节点是否有多颗子树.. 注意 这个是写在if (!vis[u])里面的.
// case 2 u是叶子节点, 割点条件是low[v]>=dfn[u]
if ( pa[u] && low[v] >= dfn[u]) ans.insert(u); // 说明v无法连接到u的祖先.
// 桥 的条件是: low[v] > dfn[u]
if (low[v] > dfn[u]) ans_pt.insert(Point(min(u, v), max(v, u))); // 说明v无法连接到u或者u的祖先.
} else {
low[u] = min(low[u], dfn[v]); // u v 为回边
}
}
}
*/
void Tarjan(int u, int fa) {
int i, v, child = ;
dfn[u] = low[u] = ++dfn_num;
for (i=head[u]; i; i=edge[i].lst) {
v = edge[i].to;
if (v == fa) continue;
if (!dfn[v]) { // 树边, 父子边
Tarjan(v, u);
child++;
low[u] = min(low[u], low[v]);
// case 1 u是根节点,同时只是有2颗子树---> 无向图 所以可能有多个根节点.
if (fa==u && child>=) ans.insert(u) ; // 根节点是否有多颗子树.. 注意 这个是写在if (!vis[u])里面的.
// case 2 u是叶子节点, 割点条件是low[v]>=dfn[u]
if (fa!=u && low[v] >= dfn[u]) ans.insert(u); // 说明v无法连接到u的祖先.
// 桥 的条件是: low[v] > dfn[u]
if (low[v] > dfn[u]) ans_pt.insert(Point(min(u, v), max(v, u))); // 说明v无法连接到u或者u的祖先.
} else {
low[u] = min(low[u], dfn[v]); // u v 为回边
}
}
} int main()
{
// freopen("E:\\input.txt", "r", stdin);
int n, m;
int u, v, i, j;
scanf("%d%d", &n, &m);
for (i=; i<=m; ++i) {
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
Tarjan(, ); if (ans.size()) {
bool flag = true; for (auto iter : ans) {
if (flag) {
printf("%d", iter);
flag = false;
} else printf(" %d", iter);
}
} else {
printf("Null");
}
printf("\n");
for (auto iter : ans_pt)
printf("%d %d\n", iter.u, iter.v); return ;
}
连通度 : 连通图的连通程度. 分为点连通 和 边连通.
割点:在连通图中,删除了连通图的某个点以及与这个点相连的边后,图不再连通。这样的点就是割点。
割边:在连通图中,删除了连通图的某条边后,图不再连通。这样的边被称为割边,也叫做桥。
DFS搜索树:用DFS对图进行遍历时,按照遍历次序的不同,我们可以得到一棵DFS搜索树。
树边:在搜索树中的蓝色线所示,可理解为在DFS过程中访问未访问节点时所经过的边,也称为父子边
回边:在搜索树中的橙色线所示,可理解为在DFS过程中遇到已访问节点时所经过的边,也称为返祖边、后向边
求割点 割边(桥)
注意 low[]和求连通分量的意义不同
求连通分量的low[]的意思是,节点u能访问的最小时间戳
求割点 桥 的low[]的意思是 顶点u及其子树中的点,通过非父子边(回边),能够回溯到的最早的点(dfn最小)的dfn值
void Tarjan(int u, int fa) {
int i, v, child = ;
dfn[u] = low[u] = ++dfn_num;
for (i=head[u]; i; i=edge[i].lst) {
v = edge[i].to;
if (v == fa) continue;
if (!dfn[v]) { // 树边, 父子边
Tarjan(v, u);
child++;
low[u] = min(low[u], low[v]);
// case 1 u是根节点,同时只是有2颗子树---> 无向图 所以可能有多个根节点.
if (fa==u && child>=) ans.insert(u) ; // 根节点是否有多颗子树.. 注意 这个是写在if (!vis[u])里面的.
// case 2 u是叶子节点, 割点条件是low[v]>=dfn[u]
if (fa!=u && low[v] >= dfn[u]) ans.insert(u); // 说明v无法连接到u的祖先.
// 桥 的条件是: low[v] > dfn[u]
if (low[v] > dfn[u]) ans_pt.insert(Point(u, v)); // 说明v无法连接到u或者u的祖先.
} else {
low[u] = min(low[u], dfn[v]); // u v 为回边
}
}
}
求割点 割边 Tarjan的更多相关文章
- tarjan求割点割边的思考
这个文章的思路是按照这里来的.这里讨论的都是无向图.应该有向图也差不多. 1.如何求割点 首先来看求割点.割点必须满足去掉其以后,图被分割.tarjan算法考虑了两个: 根节点如果有两颗及以上子树,它 ...
- 无向连通图求割点(tarjan算法去掉改割点剩下的联通分量数目)
poj2117 Electricity Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 3603 Accepted: 12 ...
- UVA 315 求割点 模板 Tarjan
D - D Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Pract ...
- poj_1144Network(tarjan求割点)
poj_1144Network(tarjan求割点) 标签: tarjan 割点割边模板 题目链接 Network Time Limit: 1000MS Memory Limit: 10000K To ...
- tarjan 割点 割边
by GeneralLiu tarjan 求 割点 割边 无向图 的 割点 割边: 对于无向连通图来说, 如果删除 一个点以及与它相连的边 之后, 使得这个图不连通, 那么该点为割点 : ...
- poj1523 求割点 tarjan
SPF Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7678 Accepted: 3489 Description C ...
- [UVA315]Network(tarjan, 求割点)
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- Tarjan求割点(割顶) 割边(桥)
割点的定义: 感性理解,所谓割点就是在无向连通图中去掉这个点和所有和这个点有关的边之后,原先连通的块就会相互分离变成至少两个分离的连通块的点. 举个例子: 图中的4号点就是割点,因为去掉4号点和有关边 ...
- Tarjan 强连通分量 及 双联通分量(求割点,割边)
Tarjan 强连通分量 及 双联通分量(求割点,割边) 众所周知,Tarjan的三大算法分别为 (1) 有向图的强联通分量 (2) 无向图的双联通分量(求割点,桥) ...
随机推荐
- 浅谈table、form 标签
1.<table> 标签 1.1包含的元素 <caption></caption>:表头信息. <tr></tr> :定义一个表格行: &l ...
- Django之REST framework源码分析
前言: Django REST framework,是1个基于Django搭建 REST风格API的框架: 1.什么是API呢? API就是访问即可获取数据的url地址,下面是一个最简单的 Djang ...
- 【转】vue+axios 前端实现登录拦截(路由拦截、http拦截)
一.路由拦截 登录拦截逻辑 第一步:路由拦截 首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录.如果用户已经登录,则顺利进入路由, 否则就进入登录 ...
- Mysql优化要点
优化MySQL Mysql优化要点 慢查询 Explain mysql慢查询 注意事项 SELECT语句务必指明字段名称 SELECT *增加很多不必要的消耗(cpu.io.内存.网络带宽):增加了使 ...
- linux文件管理 文件权限
文件权限介绍 [root@ssgao1987 ~]# ls -l 总用量 24 -rw-------. 1 root root 1161 7月 8 10:30 anaconda-ks.cfg - ...
- shell 通配符
Bash中的通配符 '?' 匹配一个任意字符 '*' 匹配0个或任意多个字符,也就是可以匹配任何内容 '[]' 匹配括号中任意一个字符.例如[abc]代表一定匹配一个字符,或者是a,或者是b,或者是c ...
- Win10系列:VC++ Direct3D模板介绍2
(3)CreateDeviceResources函数 CreateDeviceResources函数默认添加在CubeRenderer.cpp源文件中,此函数用于创建着色器和立体图形顶点.接下来分别介 ...
- 北邮新生排位赛2解题报告a-c
A. 丁神去谷歌 2014新生暑假个人排位赛02 时间限制 1000 ms 内存限制 65536 KB 题目描述 丁神要去Google上班了,去之前丁神想再做一道水题,但时间不多了,所以他希望题目做起 ...
- 《Python》网络编程基础
计算机网络的发展及基础网络概念 问题:网络到底是什么?计算机之间是如何通信的? 早期 : 联机 以太网 : 局域网与交换机 广播 主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无 ...
- SpringMVC防止表单重复提交
最近公司上线,有同志进行攻击,表当防重复提交也没有弄,交给我 ,本人以前也没弄过,知道大概的思路,但是那样实在是太麻烦了,虽然后面试过使用过滤器加拦截器实现,不过还是有点小麻烦. 后来在网上搜索后发现 ...