注意一个点可能在它的邻点回溯时被多次判为割点!
错误写法:
void tarjan(int u) {
dfn[u] = low[u] = ++tim;
int cnt = 0;
for(int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if(!dfn[j]) {
tarjan(j);
low[u] = min(low[u], low[j]);
if(low[j] >= dfn[u]) {
++cnt;
if(u != root || cnt > 1) {
res++; //错误写法
is_cntv[u] = true;
}
}
}
else low[u] = min(low[u], dfn[j]);
}
}
正确写法:
void tarjan(int u) {
dfn[u] = low[u] = ++tim;
int cnt = 0;
for(int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if(!dfn[j]) {
tarjan(j);
low[u] = min(low[u], low[j]);
if(low[j] >= dfn[u]) {
++cnt;
if(u != root || cnt > 1) {
res = !is_cntv[u]; //可以这么写,也可以在主函数最后统计
is_cntv[u] = true;
}
}
}
else low[u] = min(low[u], dfn[j]);
}
}
数据:
4 3
1 2
1 3
1 4