割边:在联通图中,去掉某一条边,使该图某些点不能相互到达,此边即为割边。
割点:同理,在连通图中,去掉某个点及与这个点相连的边,使该图有点不连通,此点即为割点。
搜索树:从某一点开始dfs遍历所有点且不重复的情况下经过的边构成的树。
tarjan算法中关键的两个数组:
dfn x 时间戳数组,即为dfs遍历是首次到达x点的序号,就是按照遍历顺序给所有点编号。
low x 在以x为根节点的子树中,时间戳的最小值。(tarjan算法中low数组的作用并不完全和一样的)。
主要做法:
dfs遍历求出dfn数组,回溯时求出low数组。
若y是x的子节点,且low y >dfn x,则(x,y)为一条割边。
从数组定义来解释:low y > dfn x 意思是不经过(x,y)这条边,y永远无法到达x或者x上面dfn比x小的点,如果切断(x,y)这条边,那至少x,y点就不能相互到达了,所以(x,y)为割边。
割边代码:
void tarjan(int x,int p)
{
low[x]=dfn[x]=++num; //先赋初值;
for(int i=linkk[x];i;i=e[i].next) //用链接表来遍历;
{
if(!dfn[e[i].y]) //如果未访问过
{
tarjan(e[i].y,x); //遍历
low[x]=min(low[e[i].y],low[x]); //回溯时更新;
if(low[e[i].y]>dfn[x]) //判断
{
c[i]=true; //c是存边的bool数组,表示该边是否为割边;
}
}
else if(e[i].y!=p) //考虑返祖边;
{
low[x]=min(low[x],dfn[e[i].y])
}
}
}
其实割点的代码和割边的代码非常像。
判断条件为:
low y >=low x (x为y的父节点)
在割边中,我们不能经过(x,y)这条边,但是在割点是可以经过的。
相等时意思是以y为根节点的子树中能连到最往上(dfn最小)的边就是x了
因为割点会割掉与该点相连的边,所以这仅存的边也会被割掉,至少x上面的点与y就不连通了。
我这样说只是为了更好理解,并不完全正确。
代码就不给了。
GG