图论基础算法之割边割点,没想到为了调整各种细节还花了我不少时间
无向图中的tarjan
算法说明
图论算法没有图很难说明,在此只做最简单的叙述就好
首先对于一张图进行DFS,由DFS过程引入三个概念:
- 时间截:节点进行DFS的时间顺序编号
- 搜索树:深搜路径的生成树
- 追溯值:一个节点不通过父节点能够到达其他节点的最早时间截
分别用 d f s [ n ] dfs[n] dfs[n]、 l o w [ n ] low[n] low[n]表示时间截和追溯值
很容易可以想象出,如果:
-
存在一个节点的子节点满足:
d f s [ p o s ] < = l o w [ c h i l d ] dfs[pos]<=low[child] dfs[pos]<=low[child]
则说明有至少一个由子节点构成的连通块除了通过搜索树,没有其他路径回到树的根节点
所以该点删除后必然产生一个独立的连通块,此时该点为割点tips:当pos为根节点时,需要存在两个child节点满足条件才可判断根节点为割点
-
存在一条边满足:
d f s [ p o s ] < l o w [ c h i l d ] dfs[pos]<low[child] dfs[pos]<low[child]
则说明通过该边的子节点的子搜索树中没有其他能通往根节点的路径
删掉该边后产生新的连通块,所以此边为割边
代码实现
原理很好理解,但是在代码实现和做题过程中,我遇到了不少的问题,接下来对犯过的错误和需要注意的点进行记录
luogu模板题
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <utility>
using namespace std;
struct Edge
{
int from;
int to;
int next;
} ed[200005];
int head[20005];
int low[20005];
int dfs[20005];
bool isAns[20005];
int num;
int n, m;