AtCoder Beginner Contest 244 G - Construct Good Path
题意
在一张 \(n\) 个点 \(m\) 条无向边组成的图中找到一条长度不超过 \(4K\) 的路径
再给定字符串 \(S\),如果 \(S_i=1\),则找出的这条路径中点 \(i\) 出现的次数必须是奇数次,反之必须是偶数次
输出任意一条符合情况的路径
思路
考虑任意找一个点为根,删除一些边使得图变成一张生成树(较为好看,也好处理),这里我找了任意一个 \(S_{root}=1\) 的 \(root\) 点作为根
首先 \(dfs\) 处理出这个生成树,存图
其后再 \(dfs\) 一次,维护一个 \(bool\) 数组 \(needDFS\),如果 \(i\) 点及其子树中存在任意一个点 \(j\) 满足 \(S_j=1\),那么 \(needDFS[i]=true\)
根据以上处理,最后我们从 \(root\) 点重新出发 \(dfs\) 第三遍,开始寻找答案
因为需要保证 \(S_p=0\) 的那些点访问偶数次,而过程中肯定是需要经过这些点的,所以这里根据 dfs 序的想法,从根节点搜索下去,再返回,这样经过两次来保证偶数次,其余特殊情况下面再处理,这里只是想法来源的说明
假设当前搜索到了点 \(u\),将点 \(u\) 加入答案队列,然后枚举它的所有子节点 \(v\),只要 \(needDFS[v]=true\),就继续搜索点 \(v\)
注意,如果这里对子节点 \(v\) 进行了搜索,则从子树返回的时候需要再将点 \(u\) 加入答案队列来保证路径的连通,然后继续再看其他子节点
最后,处理完点 \(u\) 的所有子节点后,这里就需要返回了,之后就不再看点 \(u\) 及其子树了,因此在返回之前需要检查一下是否此时点 \(u\) 的访问次数奇偶性满足条件了
- 如果已经满足条件,则直接返回上一层父节点继续 \(dfs\) 即可
- 如果没有,因为这里假设子树的访问次数已经符合题意了,所以拿点 \(u\) 及其父节点与其刷步数,按顺序将点 \(u\) 的父节点 \(fa\) 加入队列,再将点 \(u\) 加入队列一次,这样点 \(u\) 的访问次数的奇偶性就改变了
- 需要注意的是,如果当前点 \(u\) 已经是根节点,没有父节点,就不能这样做,反之,这种情况下答案序列的最后一个点一定是点 \(u\),因此将队列尾的点 \(u\) pop掉就可以,表示路径就不返回根节点了
程序
// Problem: G - Construct Good Path
// Contest: AtCoder - AtCoder Beginner Contest 244
// URL: https://atcoder.jp/contests/abc244/tasks/abc244_g
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Author: StelaYuri
// Import Time: 2022-03-20 20:54:20.532
//
// Powered by CP Editor (https://cpeditor.org)
// Template Ver.220227
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include