CF850D Tournament Construction
一个和群里大佬们不一样的做法qwq。
一道很有意思的构造题
一、算法要素:竞赛图+兰道定理+dp+dfs+一些奇怪的结论
二、前置知识:
竞赛图:
一张完全图,不过每一条边都是有向边
兰道定理:
内容:
存在一张竞赛图,其中\(d_i\)表示第i个点的出度,将数组\(d\)升序排序后,
当\(1\leq i \leq n\)时,\(\sum_{j=1}^{i} di \leq \frac{i(i-1)}{2}\)。
当且仅当\(i=n\)时取等号。
作用:
结合其他条件一起(如是完全图,边为有向边)判定一张图是否为竞赛图。
三、解题思路:
step1:判定\(n\)的上界。
根据兰道定理,能确定\(n_{max}=61\)
step2:判定所给出的集合\(d\)能否在\(n\)的范围之内构造出一个可以成为竞赛图的情况。
这一步可以用\(dp\)解决。很容易想到\(dp\)式:\(dp[n][m][l]\)表示用前\(n\)个点,此时点的出度集合包括了\(d\)的前\(m\)个元素,
共连出\(l\)条边的情况是否成立。
显然,若最终\(n\)大于61,则无解。
step3:得出每一个点的出度。
这一步用dfs即可实现。
step4:建图。
设每个点的当前所需出度为\(ans[i]\)
用一个奇妙的思路:每次取当前出度最小的点\(i\),每次向所有未被删除的点连边,直到连满\(ans[i]\)条边。
然后所有未被删除的点\(x\)向该点连边,并将\(ans[x]-1\)。
删除当前选中的点\(i\),重复进行该过程\(n\)次。
四、其他:
关于step4中建图方式的正确性:
(1)保证所有点的所需的出度都被满足了
(2)由于每次都会删点,因此不会出现重复连边的现象
因此该方法具有正确性。
五、Code
施工ing