CF1657F
题面
给你一颗树,你需要给每个节点确定一个字符 \(c\) ,使其满足给出的 \(m\) 个限制。
设 \(T_{x,y}\) 表示 \(x\) 到 \(y\) 的路径上节点按顺序拼成的字符串。
每个限制形如:\(x,y,S\)。表示 \(T_{x,y}=S\) 或 \(T_{y,x}=S\) 。
数据范围 \(n,m,\sum|S| \le 4\times 10^5\) 。
题解
这是一道2-sat
问题哦,感觉2-sat
问题见的还是比较少的。
怎么想到呢?
考虑对一个限制 \((x_i,y_i,S_i)\),你可以认为:
- \(i\) 为真 \(\rightarrow T_{x,y}=S\) 。
- \(i\) 为假 \(\rightarrow T_{y,x}=S\) 。
然后对于一个节点 \(j\) ,有 \(26\) 个状态,分别对应 \(a\sim z\) 。
因为我们2-sat
的限制就是 "若 \(p\) 为真,则 \(q\) 为真"。
那么这里就是 "若限制 \(i\) 为真,则节点 \(j\) 上的字母为 \(c\) 为真"
而这题中是允许我们暴力在树上遍历并且标限制的。
但是开 \(4\times 10^5 \times 26\) 个节点很明显不行,考虑优化。
发现很多节点状态是无用的,比如假如我知道有一条限制经过了 \(x\) ,那么我知道 \(x\) 现在有用的状态就只有两种了(正的一遍和反的一遍),那么我们就可以对第一次扫过的点给记录上这唯一可能的两种状态。
然后直接跑2-sat
就行了。
启发
- 记录一下这种少见的
2-sat
题。 - 感觉
2-sat
一定要找 "若 \(p\) 为真,则 \(q\) 为真" 这种限制。