割点【模板】

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

相关文章

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

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

最大流、 最小费用最大流终极版模板

最大流  const int inf = 1000000000 ;const int maxn = 20000 , maxm = 500000 ;struct Edge{int v , f ,next ;Edge(){}Edge(int _v , int _f , int _next):v(_v) ,f(_f),next(_next){}};int sourse , mee

图的割点、割线问题

图的割点问题 邻接矩阵表示图 package com.hyl.algorithm.other;import java.util.Arrays;import com.hyl.algorithm.search.base.SearchIntf;import com.hyl.algorithm.search.base.SearchIntfFactory;/*** 寻找图的割点* <p>** @aut

C++语法知识点合集:11.模板

文章目录 一、非类型模板参数1.非类型模板参数的基本形式2.指针作为非类型模板参数3.引用作为非类型模板参数4.非类型模板参数的限制和陷阱:5.几个问题 二、模板的特化1.概念2.函数模板特化3.类模板特化(1)全特化(2)偏特化(3)类模板特化应用示例 三、模板分离编译1.概念2.模板的分离编译 模版总结 一、非类型模板参数 模板参数分类类型形参与非类型形参 非类型模板

Smarty模板引擎工作机制(一)

深入浅出Smarty模板引擎工作机制,我们将对比使用smarty模板引擎和没使用smarty模板引擎的两种开发方式的区别,并动手开发一个自己的模板引擎,以便加深对smarty模板引擎工作机制的理解。 在没有使用Smarty模板引擎的情况下,我们都是将PHP程序和网页模板合在一起编辑的,好比下面的源代码: <?php$title="深处浅出之Smarty模板引擎工作机制";$content=