割点【模板】

2024-01-17 00:32
文章标签 模板 割点

本文主要是介绍割点【模板】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参看资料:

https://www.cnblogs.com/maple-kingdom/p/maple-kingdom_wind.html

https://www.cnblogs.com/collectionne/p/6847240.html

https://baike.baidu.com/item/%E5%89%B2%E7%82%B9/9384042?fr=aladdin


割点集合&割点:

       在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合。

       如果某个割点集合只含有一个顶点X(也即{X}是一个割点集合),那么X称为一个割点

求割点:

     1》直接BFS;

     2》Tarjan算法:

           1> BFS搜索树,详细:https://blog.csdn.net/sodacoco/article/details/86488033;

           2> 定义 DFN (u) 为 u 在搜索树中被遍历到的次序号(时间戳);定义Low (u) 为 u 或者 u 子树中的节点经过最多一条后向边能追溯到的最早的树中节点的次序号

           根据定义,则有:

           如果 (u , v) 为树枝边,u为v的父节点,则Low (u) =Min { Low (u) , Low (v) } 。

           如果 (u , v) 为后向边,u不为v的父节点,则Low (u) =Min { Low (u) , DFN (v) } 。

           判断割点: 

           一个顶点 u 是割点,当且仅当满足以下两个条件之一:

           条件1:u 为树根,且 u 有多于一个子树,则 u 为割点;

           条件2:u 不是树根,且满足存在 (u , v) 为树枝边【即满足 u 为 v 在搜索树中的父亲】,并使得 DFN (u) <= Low (v) 。【因为删除 u 后 v 以及 v 的子树不能达到 u 的祖先】。

           代码实现:

void tarjian(int x,int pre){dfn[x]=low[x]=++dfstime;stk[++top]=x;int cnt=0;for(int i=head[x];i!=-1;i=next[i]){int y=to[i];if(!dfn[y]){cnt++;tarjian(y,x);low[x]=min(low[x],low[y]);//判断割点两个条件,且不用判断重边//对于割点来说,两个点多条边和一条边效果一样if(x==root&&cnt>1||(x!=root&&dfn[x]<=low[y]))//判断割点cut[x]=1;}else low=min(low[x],dfn[y]);//无向图,不用判断是否在栈中}
}

           例题:

题目描述

给出一个n个点,m条边的无向图,求图的割点。

输入格式:

第一行输入n,m

下面m行每行输入x,y表示x到y有一条边

输出格式:

第一行输出割点个数

第二行按照节点编号从小到大输出节点,用空格隔开

输入样例#1: 

6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

输出样例#1: 

1 
5

说明

n,m均为100000

tarjan 图不一定联通!!!

 

注意与tarjan 求强连通分量的方法区别。

求割点不需要用到栈。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;int N,M,x,y,cnt,Index,ans=0;
int first[100010],next[200010];
int dfn[100010],low[100010];
bool del[100010];struct maple{int f,t;
}Rode[200010];void Build(int f,int t)
{Rode[++cnt]=(maple){f,t};next[cnt]=first[f];first[f]=cnt;
}void Tarjan(int n,int fa)
{int cd=0;dfn[n]=low[n]=++Index;for(int i=first[n];i;i=next[i]){if(!dfn[Rode[i].t]){Tarjan(Rode[i].t,n);low[n]=min(low[n],low[Rode[i].t]); // 更新n能向上回溯到的最小时间戳 if(low[Rode[i].t]>=dfn[n]&&fa!=-1) // 如果n的子树中最多能追溯到n,并且n不为根的话, del[n]=1;                     //就为一个割点,根要特殊处理if(fa==-1) ++cd;  // 统计根的子树 }else if(Rode[i].t!=fa)  low[n]=min(low[n],dfn[Rode[i].t]);}if(fa==-1&&cd>=2) del[n]=1; // 如果n为根且n的子树数量大于等于 2 ,即为一个割点 
}
int main()
{scanf("%d%d",&N,&M);for(int i=1;i<=M;++i){scanf("%d%d",&x,&y);Build(x,y);Build(y,x);}for(int i=1;i<=N;++i)if(!dfn[i]) Tarjan(i,-1);for(int i=1;i<=N;++i) if(del[i]) ++ans;printf("%d\n",ans);for(int i=1;i<=N;++i) if(del[i])printf("%d ",i);return 0;
}

 

这篇关于割点【模板】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/614405

相关文章

Java如何根据word模板导出数据

《Java如何根据word模板导出数据》这篇文章主要为大家详细介绍了Java如何实现根据word模板导出数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... pom.XML文件导入依赖 <dependency> <groupId>cn.afterturn</groupId>

Python中Flask模板的使用与高级技巧详解

《Python中Flask模板的使用与高级技巧详解》在Web开发中,直接将HTML代码写在Python文件中会导致诸多问题,Flask内置了Jinja2模板引擎,完美解决了这些问题,下面我们就来看看F... 目录一、模板渲染基础1.1 为什么需要模板引擎1.2 第一个模板渲染示例1.3 模板渲染原理二、模板

利用Python打造一个Excel记账模板

《利用Python打造一个Excel记账模板》这篇文章主要为大家详细介绍了如何使用Python打造一个超实用的Excel记账模板,可以帮助大家高效管理财务,迈向财富自由之路,感兴趣的小伙伴快跟随小编一... 目录设置预算百分比超支标红预警记账模板功能介绍基础记账预算管理可视化分析摸鱼时间理财法碎片时间利用财

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

基于Java实现模板填充Word

《基于Java实现模板填充Word》这篇文章主要为大家详细介绍了如何用Java实现按产品经理提供的Word模板填充数据,并以word或pdf形式导出,有需要的小伙伴可以参考一下... Java实现按模板填充wor编程d本文讲解的需求是:我们需要把数据库中的某些数据按照 产品经理提供的 word模板,把数据

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n