「JOISC 2017 Day 3」自然公园(交互)
交互题。后台有一个 \(n\) 个点 \(m\) 条边的无向图。每次,你可以询问两点 \(x, y\) 只经过某个集合 \(S\) 中的点时能否互相到达。你要用不超过 \(45000\) 次询问问出这个图。
\(n, m \le 1500\),且每个点度数不超过 \(7\)。
分析:
抄的这篇,查重率伯分之伯。
考虑维护 \(0\) 所在的连通块,每次加一个和它相邻的点。假设已经知道了 \(x\) 和当前连通块相邻,考虑如何问出所有 \(x\) 和块内连的边。考虑给连通块钦定一个根 \(r\),再搞出一个序,满足每个前缀都连通(dfs 和 bfs 序均可)。再进行二分,每次查 \(S\) 为序的一个前缀时 \(r\) 和 \(x\) 是否连通。这样就能问出和 \(x\) 相邻的序最小的点。把它挖掉,对每个子连通块递归地做即可。由于做每个子连通块前都要问一遍这个块和 \(x\) 是否相邻,所以额外要用 \(7m\) 次操作。
再考虑怎么找 \(x\)。其实不用显式地找,考虑每次随一个块外的点 \(z\),把连通块到 \(z\) 的一条路径上的点依次加进去。通过类似的问一个前缀的二分,可以问出路径上的某点 \(y\)。之后先做连通块到 \(y\) 的路径,再继续做 \(z\) 即可。为了避免 \(z\) 找到 \(y\),\(y\) 又找回 \(z\) 的情况,做 \(y\) 时要先把 \(z\) 删掉。详见代码。