很简单,对吧?DFS 或者 BFS 一遍,EZ 秒了。
我要 BFS!
这张图能够给出几乎所有 hack。考虑 BFS,\(f_i\) 表示 \(i\) 的能到达节点,显然在这里转移是 \(f_u=\sum f_v\),\(v\) 为 \(u\) 的所有直接后继。那么在图中,\(f_1=f_2+f_5\) 会导致 \(4\) 被算重。
这是错误的。
我要 DFS!
每次随便选一个没选过的节点作为 DFS 起点 \(now\),给经过的每个没访问过的节点都打上 \(tag_u=now\),每次转移判断如果没访问过直接给 \(f_u\) 加 \(f_v\),访问过且不是本次 DFS 访问到的(即 \(tag_u\neq now\))就加上 \(f_v\)。看起来挺理想的,但是在上图中,如果你选择 \(8\) 为一开始 DFS 的节点,经过 \(8,7,6,4\),然后在选 \(1\) 开始 DFS,这时候 \(5,3\) 的后继都是不是本次 DFS 访问到的节点,都直接加 \(f_6+f_4\),\(4\) 节点仍然算重。
这是错误的。
我要……
对于任意 DAG 目前现存唯一正确解就是用 bitset 维护可达点集合然后每次转移取并集。但是如果题目中 DAG 有一定规律那么可以利用它快速完成取并集的操作,比如,可达的节点一定是一段连续的区间。
最后,如果有哪位天才想出了线性做法请第一时间让我知道,谢谢。