$割点割顶tarjan$
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline LL read () {
LL res = ;
int f () ;
char ch = getchar ();
while (!isdigit(ch)) {
if (ch == '-') f = - ;
ch = getchar();
}
while (isdigit(ch)) res = (res << ) + (res << ) + (ch ^ ),ch = getchar();
return res * f ;
}
const int N = +;
int a[N] , nxt [N] , head[N] , dfn[N] , low[N] , cnt , k ;
bool cut[N] , bst[N] ;
inline void Add (int x ,int y) {
a[++k] = y ; nxt[k] = head[x]; head[x] = k ; return ;
}
inline void tarjan (int u,int mr) {
int rc = ;
dfn[u] = low[u] = ++ cnt ;
for ( register int p = head[u] ; p ; p = nxt[p] ) {
int v = a[p] ;
if (! dfn [v]) {
tarjan ( v , mr ) ;
low[u] = min ( low[u] , low[v] );
if (low[v] >= dfn[u] and u != mr) cut[u]=true;
if (u == mr) rc ++ ;
}
low[u] = min ( low[u] , dfn[v] ) ;
}
if (u == mr and rc >= ) cut[mr] = true;
}
signed main() {
int n = read() ;
int m = read() ;
int ans = ;
for ( register int i = ;i <= m ; i ++) {
int x = read() ;
int y = read() ;
Add (x,y) ; Add (y,x) ;
}
for ( register int i = ;i <= n ; i ++)
if ( ! dfn[i] ) tarjan ( i , i ) ;
for ( register int i = ;i <= n ; i ++)
if ( cut[i] ) ans ++ ;
cout << ans << endl ;
for ( register int i = ;i <= n ; i ++)
if ( cut[i] ) cout << i << ' ' ;
return ;
}
首先tarjan求割点的重点就是dfn和low数组的理解。
dfn[i]就是时间戳,即在什么时刻搜索到了点i,
low[i]则是i点能回溯到的dfn最小的祖先,
搜索的时候判断一下当对于点x存在儿子节点y,使得dfn[x]<=low[y]则x一定是割点。
因为只要x的子节点不能回溯到x的上面,就是没有返祖边超过x点,那么割掉x就能造成不连通了
好啦,基本算法介绍完,就要讲几个问题了。
首先,为什么此处
low[a]=min(low[a],dfn[p]);
不能写作
low[a]=min(low[a],low[p]);
在我的理解,由于此处是一张无向图,我们有双向建了边,导致节点可以回溯到它的父节点;
而如果从它的父节点或其父节点的另一棵子树上有向上很多的返祖边,
这时把子节点的low值赋为父节点的low,就可能导致其low==其父节点low<其父节点dfn,
从而使本该是割点的点被忽视了,答案就少了,所以就wa了。
另外本题还有几个注意点:
给的图不一定是连通图,即求每个联通块的割顶
输出格式别看错了2333
链式前向星开边要2倍
随机推荐
- Oracle锁表数据查询及解决方法
首先:查询数据那些表被锁定1. SELECT l.session_id sid, s.serial#, l.locked_mode,l.oracle_username, l.os_user_name, ...
- 如何将一个本来需要发几十条sql语句的需求优化成两条(非sql语句优化,而是解决方法)
首先声明,本人所有博客均为原创,谢绝转载! 今天接到一个需求,如下 这里解释一下,为什么是几十条,因为这里面每个公式的每个条件都是一个单独的数据如净利润就是一条sql语句,而且分散在不同的表,如果此方 ...
- 【ZJOI2017 Round1后记】
2017.4.1: NOIP+Round1综合成绩出来,标准分离续命线差了80分,果然还是联赛坑挖太大了…… 不管怎么说能续命的话还是要试一下的…… 发毒誓:Round2前不打手游,不看NGA,不看星 ...
- CODEVS——T 3736 【HR】万花丛中2
http://codevs.cn/problem/3736/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description ...
- 【转载】Spring Boot【快速入门】2019.05.19
原文出处:https://www.cnblogs.com/wmyskxz/p/9010832.html Spring Boot 概述 Build Anything with Spring Boot ...
- JSP的异常处理
以下内容引用自http://wiki.jikexueyuan.com/project/jsp/exception-handling.html: 当写JSP代码的时候,有可能会留下一个编码错误,并且它会 ...
- 深度学习——练习
对于深度学习的基础,线性回归以及逻辑回归,下面针对这两个方面做一个练习. 例子主要参考http://openclassroom.stanford.edu/MainFolder/CoursePage.p ...
- Mybatis中insert中返回主键ID的方法
<insertid=“doSomething"parameterType="map"useGeneratedKeys="true"keyProp ...
- JavaSE入门学习5:Java基础语法之keyword,标识符,凝视,常量和变量
一keyword keyword概述:Java语言中有一些具有特殊用途的词被称为keyword.keyword对Java的编译器有着特殊的意义.在程 序中应用时一定要谨慎. keyword特点:组成k ...
- 【C/C++多线程编程之五】pthread线程深入理解
多线程编程之pthread线程深入理解 Pthread是 POSIX threads 的简称,是POSIX的线程标准. 前几篇博客已经能给你初步的多线程概念.在进一步学 ...