蒟蒻做的第一道网络流构造题,太经典了故写题解已记之。
大多数题解都是直接从网络流角度来考虑,我觉得这样并不合适,如果比赛的时候没有TAG给你点,像这种类型的问题都很容易往找规律上靠(但此题确实可以找规律)。
于是我们引入一个叫“隐式图”的概念。
隐式图顾名思义,大白话来讲就是题目看着不像是图论,但是可以通过一些限制或关联进行建点,连边,最终通过图论的一些算法来求解。
那么就此题来看,经思考一会可发现这题的柱子并没有什么实际的作用,所有的操作都是关于珠子的编号的。那么我们可以以每一个珠子为点,若满足条件(编号相加为平方数)就两两连边,那么就可得到这样一张图:
具体怎么连放代码里说。
题目要你求 “对于给定的n,计算在n根柱子上最多能放多少个球”,转化成图的问题就是 “对于给定的n,计算不超过n条路径最多可以覆盖多少满足条件的节点”,如果您已经学了$DAG$的一些二分图相关性质,应该就知道了:
最小边覆盖=点总数-最大匹配。
有这么个性质,于是再将此图进行拆点,转化成二分图的形式,每加一个点就在上面跑匈牙利/网络流并统计总匹配,如果发现 点总数-最大匹配>最小边覆盖
那就退出。
但是值得注意的是, 我们每次重新跑网络流时,都是在跑残量网络,意思就是我们每次所得的最大流都是增加的匹配数,所以就再搞个变量累加得到总的匹配数。
但是另一个子问题是求他的路径。
其实把网络流原理搞懂了也不难,二分图里的网络流路径等价于他把流量跑满的路径(流量均为1),于是最后对每个点都找一遍,看到哪个点满流他的下一步就是那个点,储存一下最后输出即可。
上我丑陋的代码:
1 |
|