题解:CF732E Sockets
太好玩了这道题。
题目要求在给定 \(n\) 台电脑功率 \(p_i\) 和 \(m\) 个插座功率 \(s_j\) 的情况下,先让可连接电脑数 \(c\) 最大,其次使所用适配器总数 \(u\) 最小,并输出一组合法方案。适配器把功率 \(x\) 改成 \(\lceil x/2\rceil\),且一根插座可串联无穷多根适配器。
观察到,一只插座功率每降一次就会落入严格小于原来的区间,因此一只插座最多降 \(\lceil\log_2 10^9\rceil\le 30\) 次就会变成 \(1\),所以整道题天然有 \(30\) 层功率层。如果我们把“给某插座再接一只适配器”理解为把它从第 \(t\) 层搬到第 \(t+1\) 层,那么只要分层广搜就能保证对任何插座找到的第一次匹配一定使用了最少的适配器数。
做法如下。先把所有电脑按功率散列到一张哈希表,每个键是一种功率,值是该功率电脑的单向链表表头,这样能 \(O(1)\) 把链首弹出完成匹配。然后建立 \(31\) 条队列 \(q[0],q[1],\dots,q[30]\),第 \(t\) 条队列里存目前已经使用了 \(t\) 只适配器、当前功率为 \(x\) 的插座编号。初始化时所有插座进 \(q[0]\)。接下来从 \(t=0\) 层开始依次扫描:弹出队头插座 \(j\),若其功率 \(x\) 在哈希表中还有电脑未匹配,就立即配对;否则若 \(x>1\),就把功率改成 \(\lceil x/2\rceil\)、适配器数 \(t+1\) 并扔进下一层队列。因为整个过程严格按照层次序推进,所以配对成功时那只插座使用的适配器数就是全局最小;所有能配上的电脑都被尽量匹配,因此 \(c\) 也达到最大。
正确性简洁地说:把“接一只适配器”看成一步,首度出队必为最短步数;又因每只插座沿唯一路径下降,所以不存在更小 \(u\) 的方案。若有方案能配更多电脑,则该方案在某只电脑的功率层必然早于本文算法配到,但广搜是层优先的,矛盾。因此 \((c,u)\) 同时最优。
时间复杂度 \(O((n+m)\log V)\),其中 \(V\) 为值域。

浙公网安备 33010602011771号