c++课程总结——Tarjan缩点

本文介绍了Tarjan算法用于寻找有向图中的强连通分量,通过DFS和dfn、low数组以及栈来实现。算法步骤包括初始化dfn和low值,递归遍历图,更新low值并判断环,最后通过栈记录并反向输出环。还提供了一个例题和对应的解题思路。
摘要由CSDN通过智能技术生成

Tarjan缩点

引入

  • 有向图的强连通:图中任意两点可以互相到达强连通
  • 那么什么是强连通分量
  • 就是指有向图中的一部分构成强连通,称这部分为强连通分量,下图中的B,C,D,就构成了强连通分量。
    强连通分量
  • Tarjan缩点算法就是为了找到有向图强连通分量

实现

  • 算法依靠dfs,用一个dfn[] 数组,一个low[] 数组,以及一个实现上述功能。
  • 时间戳,即,访问有向图一个节点的时刻。如下图,dfs后A的时间戳为1,B的时间戳为2,C为3,E为4,D为5,F为6,以此类推。这个即为dfn[] 数组所存的数据。作用:判断一个节点是否被访问过。
    在这里插入图片描述
  • low[] 数组,存放能到达的最靠前的点的时间戳,初始值指向本身的时间戳。如下图,左边的数字为dfn,右边为low,C,D的low值都指向B的时间戳2。用途,如图D指向了B而他们的low值一样,不难发现,有一个环,所以low是用来判环的。
  • 那么low的值是如何赋予的?很简单,用该点指向的点的low值更新,也就是取一个min。
  • 最后找到了环,怎么取出呢?这就用到了栈。
    在这里插入图片描述

流程

1.for循环寻找一个dfn为0的点,将该点dfn和low值均赋予时间戳的值,时间戳值再加1;
2.将该点压入栈
3.寻找该点指向的点,判断是否访问过
4.如果没有访问,重复1~3递归,然后更新该点low值
5.如果访问过直接更新low值
6.回溯过程中,找到第一个dfn与low相同的点,该点即为环的一点,它的子树就构成一个环
7.假设当前点为x,不断将栈顶弹出并记录,当栈顶与x相同,则表示该环已取出。

  • 不难发现,根据上述流程,栈内应该是下图这样,弹出的顺序为D,C,B,但有向图是有方向的,显然顺序是反的,所以我们就要反向输出。
    在这里插入图片描述

例题

题目大意:一个有向图有 N N N个顶点 N N N条边,输入 A [ i ] A[i] A[i],第 i i i条边是 i 到 A [ i ] i到A[i] iA[i],找到一个没有重复点出现的循环,可以证明,存在解决方案。<

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值