题目链接:点击查看
题目大意:给出一张 n 个点 m 条边的无向图,现在需要将这张图转换为有向图,并且使得 k 个可达条件成立,输出一种构造方案
题目分析:如果在无向图中出现环的话,那么在转换为有向图后,环上的点一定是可以使得互相可达的,所以我们考虑 tarjan 边双缩点,将整个图缩成一棵树,在缩边的时候,只需要在 dfs 树上一直加边就可以构造环了
现在只需要考虑缩边后的树边方向即可,对于一个可达条件的限制 ( x , y ) ,设是需要从 x -> y,因为在一棵树上路径唯一,我们先求出 lca = LCA( x , y ) ,维护两个数组 in 和 out ,其意义分别是:
- in[ i ] :有 in[ i ] 条边的方向需要从 fa[ i ] -> i
- out[ i ] :有 out[ i ] 条边的方向需要从 i -> fa[ i ]
对于一条边 ( x , y ) ,可以用树链剖分,分别维护 x -> lca 和 lca -> y 这两段的边上的 in 数组和 out 数组,最后对于某条边来说,如果 in[ i ] 和 out[ i ] 皆不为 0 的话,那么显然是无解的,否则根据上面的两种情况确定一下
不过马哥有个很棒的想法,就是用树上差分来代替树链剖分,对于一个要求 ( x , y ) 来说,只需要让 out[ x ] ++ , out[ lca ] -- , in[ y ] ++ , in[ lca ] -- ,最后一遍 dfs 统计一下树上前缀和就好了,时空复杂度以及代码难度相对树链剖分来说都优秀太多了
剩下的就是实现了,耐心码就好了,没什么坑点
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include