ARC092D Two Faced Edges

题意:给出一张 个点 条边的有向图,保证不存在重边和自环。

对于每条边,判断将其反向后(其他边不变),图中强连通分量的数量是否改变。

,,时限 。


对于边 ,若将其反向:

  • 若 在同一个强连通分量内。

    强连通分量个数不可能增加,但该强连通分量可能被破坏。

    若图中存在一条 的路径,且不含该边,则不会破坏,反之则会。

  • 若 不在同一个强连通分量内。

    若图中存在一条 的路径,且不含该边,则会增加一个强连通分量,反之无变化。

记 表示“ 在同一个强连通分量内”, 表示图中存在 的路径,且不含边 。

综上所述,只有 两者之一成立,边 的答案才为 ,否则为 。

对于 ,容易使用 Tarjan 算法求出。问题的核心在于 的求解。

算法一

考虑对于每个 分别求出 。

从 开始 dfs ,将 的边表顺序翻转,再次 dfs。

若点 在两个 dfs 树中深度均为 ,则说明 ,否则 。

证明:

若 ,则点 在两个 dfs 树中深度显然均为 。

下证点 在两个 dfs 树中深度均为 时, 。即 时 在两个 dfs 树中深度不可能同时为 。

时,存在另一条不走 的路径能从 到 ,记该路径的第一条边为 。

在两次 dfs 中,必然恰有一次先考虑 而后考虑 ,由于 dfs 的特性,一定会从 进而访问到 。后面考虑 时,就不会将其加入 dfs 树。

算法二

仍考虑对于每个 分别求出 。

对于某个 , 当且仅当存在 ,满足存在简单路径 。

将 点删除,将所有直接与 相连的点记为 。

顺次考虑 ,从 开始搜索(不重复遍历之前搜过的点),所有搜到的点 (除了 本身)都能满足 。

(这里用 常数较小)

为了处理 的情况,还需反过来再跑一次。

这样的搜索复杂度是 的,瓶颈在于,无论目的地是否被标记过,我们都要再次检查出边。

考虑利用 bitset 进行优化,记目前还未发现 的 的集合为 ,点 的出边的集合为 。我们搜索时,只需考虑集合 内的元素。

下面的代码段可以用 的代价找出 bitset 内的所有元素。

1
for(int i=T._Find_first(); i!=T.size(); i=T._Find_next(i))

每个点只会被搜索到一次,故复杂度为 。