联合省选 2022 学术社区 Analysis
特殊性质 B 部分分
观察到输出的合法信息数正确就可以得到 50% 的分数,而特殊性质 B 存在某个方案每条非学术消息都合法,故直接计算输入中的楼上型消息与楼下型消息的数量和即可,获得 20 分。
测试点 1
爆搜,获得 4 分。
测试点 2
状压 DP,获得 8 分。
特殊性质 ABC
注意到一条消息连接两个人并且有明显的指向关系,可以想到使用图论建模描述方案。对于每个人建立一个点,对于每条消息 A B louxia
从 B
向 A
连一条边(这是因为它之后的消息指向的是 A 不是 B),对于一条学术消息放在其发出者对应的节点上。观察合法方案,其应该由若干条链构成,每一条链从一个点的学术消息开始,在图上走一段路径,最后可以在任意一个点结束。也就是说,我们需要把图上的所有边进行覆盖。
图论中讨论到边覆盖的算法模型是欧拉回路,当然为了让链覆盖变成欧拉回路需要一些小小的技巧:建立一个虚点 T
,对于一个 A
发出的学术消息从 T
向 A
连一条边。对于每个非虚点,若其入度减出度为 d
,则从它往 T
连 d
条边。首先这个 d
一定不会是负数,否则必然存在一条从它发出的边对应的消息不符合实际情况。对新图从 T
开始跑欧拉回路得到的方案去掉所有没用的边就得到了一个合法的方案。当然还有一个问题是为啥这个图一定联通,这是因为每个人都会发一条学术消息。
该算法可以通过 7 个测试点,加上以上所有的部分分,共可以获得 42 分。
特殊性质 AC
沿用 ABC 的算法,问题在于有一些点由于入度小于出度,对于额外的(出度减去入度)条消息是一定无法满足实际情况的,由此我们可以计算出答案的一个下界。同时我们可以简单地构造一个方案使得答案恰好为这个下界:对于每个出度大于入度的点,从 T
向它连若干条边使其入出度平衡,然后跑一遍欧拉回路。对于这样加入的每一条边,它在欧拉回路中连接的下一条边对应的消息不满足实际情况,而其他消息都满足实际情况。
该算法可以额外通过 3 个测试点,加上以前所有的部分分,共可以获得 54 分。
特殊性质 BC
再一次观察最终的方案。其仍然可以划分成若干条链,因为满足特殊性质 C,所以每条链一定是若干条楼上消息+中间的一条学术消息+若干条楼下消息(若干可以是零)。这引导我们建立分层图描述方案。具体地,建立二层图 A B loushang
,在 A
向 B
连一条边;对于一条学术消息,从 A B louxia
,在 B
向 A
连一条边。那么一条方案中的链对应的就是从
仍然沿用特殊性质 ABC 的做法:建立一个虚点 T,对于每个
该算法可以额外通过 5 个测试点,加上以前所有的部分分,共可以获得 64 分。
特殊性质 C
继续沿着之前的思路走,现在不一定每条边都出现在方案里了,我们要如何选择舍弃的边呢?
之前的所有算法都在平衡图上每个点的点度以保证欧拉回路的存在,那么继续沿着这个想法行进。对于
仔细想想舍弃一条边意味着什么。对于一条 A B loushang
,如果我们舍弃它,其实意味着这条消息被我们认作了功能与学术消息等同的消息,也就是说,原本是 A B loushang
这条边,下界可以往上加 1。
这样看来,我们希望尽可能多的找到这样的边,那么下界就可以抬升得尽可能大,而这个最大值很显然对应着答案。找这样的边的过程可以使用二分图网络流模型刻画:对于每个 A B loushang
消息,从 A B louxia
消息,从
将这些边舍弃(这指的是将它们变成对应的学术边)之后,再运行 BC 和 AC 思想结合的算法得到欧拉回路即可找到对应方案。
该算法可以额外通过 5 个测试点,结合之前的所有算法可获得 80 分。
最终算法
最后一个问题是需要解决特殊性质 C 中提到的对边。其发生的变化是:链的中间不一定由一条学术消息作为中转,而是用一对 A B loushang
和 B A louxia
。我们容易对方案进行调整或者对网络流得到的最终方案进行分析,得到将这样的一对消息放在一起总是不劣的,所以将它们拼在一起之后,就变成了
该算法可以通过最后 5 个测试点,获得满分。
Bonus
如果去掉题目中的每一个在帖子中发过言的人都一定会在帖子中发出至少一条学术消息这题能不能做呢?
去掉这个条件的难点在于,
如果大家有什么想法可以与我讨论。