$割点割顶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倍
随机推荐
- mysqldump快速导数据
MySQL导出的SQL语句在导入时有可能会非常非常慢,经历过导入仅45万条记录,竟用了近3个小时.在导出时合理使用几个参数,可以大大加快导入的速度. -e 使用包括几个VALUES列表的多行INSER ...
- [COJ0970]WZJ的数据结构(负三十)
[COJ0970]WZJ的数据结构(负三十) 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为 ...
- HDU 1800 hash 找出现最多次数的字符串的次数
乘法hash: 这类hash函数利用了乘法的不相关性 int Hash(char *str){ int seed = 131 , value=0; while(*str != '\0'){ ...
- [NOIP2008] 提高组 洛谷P1149 火柴棒等式
题目描述 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 加号与等号各自 ...
- [NOIP2007] 提高组 洛谷P1097 统计数字
题目描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*10^9).已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出 ...
- 【BZOJ2301】Problem b(莫比乌斯反演)
题意:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d, 且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 1≤n≤50000,1≤a≤b≤50000 ...
- codevs2597 团伙
题目描述 Description 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友 ...
- 在 Oracle Linux 上使用 DTrace
作者:Richard Friedman 简要介绍适用于 Oracle Linux 的 DTrace 探测器和提供程序,以及与 Oracle Solaris 中 DTrace 探测器和提供程序的区别.还 ...
- html自动换行
对于div,p等块级元素 正常文字的换行(亚洲文字和非亚洲文字)元素拥有默认的white-space:normal,当定义的宽度之后自动换行html css 1.(IE浏览器)连续的英文字符和阿拉伯数 ...
- 几种常见排序算法的java实现
一.几种常见的排序算法性能比較 排序算法 最好时间 平均时间 最坏时间 辅助内存 稳定性 备注 简单选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 n小时较好 直接插入排序 O( ...