LG-P3552 [POI2013]SPA-Walk Solution

更好的阅读体验戳此进入

(建议您从上方链接进入我的个人网站查看此 Blog,在 Luogu 中图片会被墙掉,部分 Markdown 也会失效)

题面

存在 2n 个长度为 n01 串,两个 01 串之间有边当且仅当两者之间仅有一位不同,或者说 x,y 之间有边当且仅当 xy=2t。我们称这样的一个图为 n 维超立方体(n-dimensional hipercube)。现在从这其中去掉 k 个串 s1,s2,,sk,给定两个串 S,T,求两者之间是否能够到达。

能到达输出 TAK,反之输出 NIE

1n60,0kmin(106,2n1),n×k5×106

输入格式

n k

S T

s1

s2

sk

(偷个懒就不写文字叙述了。。。)

Solution

这道题我本来还以为是和 LG-P7966 [COCI2021-2022#2] Hiperkocka 差不多的题,该题题解,按照那道题的思路想了一下然后假了,改了一下之后 T 掉了,寄,和之前的题关系不是很大,只是定义一样。

Lemma 1:对于一个 n 维超立方体,令点集为 S,将其所有的点分为两个点集 S1,S2S1S2=S,S1S2=ϕ,则两点集之间的边集的大小一定不小于两点集之间较小者的大小,也就是 |{(u,v)|uS1,vS2,uv=2t}|=min(|S1|,|S2|)

证明:A proof is left to the reader.

证明:这东西大多数地方都没有人证明,甚至官方题解,感觉可以当成一个已知结论记住,关于严谨证明网上也找到了个大佬的证明(看不懂),戳此进入

Lemma 2:对于一个 n 维超立方体,将其删去 k 个点后,最多仅能够形成 1 个点集大小大于 n×k 的连通块。

证明:假设我们现在有两个连通块,其点集分别为 S1,S2,显然 S1S2=ϕ,我们设 |S1|,|S2|n×k,令点的全集为 S,则显然 S2SS1。我们又可以通过 Lemma 1 知道 S1S2SS1 之间的边集大小不小于 min(|S1|,|SS1|),也就是其边集 E 满足 En×k+1,也就是说如果我们想要形成这两个连通块就必须要断开至少 n×k+1 条边,而我们去掉 k 个点只能断开 n×k 条边,无法形成这两个连通块,

于是只要有了 Lemma 2,我们就可以很容易想到,令出发点和终点分别为 S,T,如果两者可以互通,那么他们要么都在唯一的大于 n×k 的连通块内,要么在某一个小于等于 n×k 的连通块内,所以我们只需要搜至多 n×k 的点数,如果两者都不在小于 n×k 的连通块中,那么一定同在唯一的大连通块中,反之如果在同一个连通块内那么一定可以被搜到。

于是我们分别从 S,T 进行爆搜,各自维护一个 unordered_set 记录其所在连通块有哪些点,如果从搜索过程中遇到另一个点了,则两者同在一个小连通块中,直接输出连通然后 exit,如果连通块大小超过 n×k 了那么直接标记一下然后 return。两者都搜完后如果两个连通块都超过 n×k 了那么一定同在一个大块,反之则一定不在同一个块,不连通。

另外个人建议把二进制转成 long long 再存,否则还会存在一个 hash 的复杂度,虽然我感觉好像嗯搞也能过???

然后写位移的时候记得写成 1ll

这个的复杂度大概是 O(n2k) 级别的,但是常数可能会很大,然后我不太确定这玩意能不能被卡成类似 O(2n) 级别的,但是因为有 n×k 这个限制感觉似乎是可以被严谨证明的,我不会

A proof is left to the reader.

然后。。。Luogu 评测记录

unordered_set 寄了,cc_hash_table 寄的更多,经典被卡常,调了亿会怎么 Luogu 上都是两个点 TLE,一个点 MLE,于是开始手搓 hash 挂链,队列之类的,最终终于在 Luogu 上把这破题给卡过去了。。。

Code

UPD

update-2022_09_27 初稿