Link
看到题目首先肯定想到差分约束,当然这也是一个差分约束的题。
题目比较难想的地方在于建图,设Dist[i][j]表示max{Ai−Aj},也就是Ai最多能比Aj大多少。那么根据题意我们知道对于第一种情况,应该是
然后对于第二种情况,题目对数量上并没有限制,限制的只是大小关系,然而我们转化一下依然能知道AY−AX≥0,对此我们选择从Y向X连一条边权为零的单项边,然后Dist[Y][X]=0,对于这种情况我们连边的目的不是为了限制数值,而是为了限制关系,大小关系。
由于限制条件可以叠加,于是对于每一个建边都要取min。
然后首先要考虑的肯定是合法问题。稍加分析我们可以知道图如果存在非零环,肯定是不合法的,于是我们考虑判断非零环。
一般来说判负环就是简单地跑一遍Spfa然后记录每一个点入队的次数就可以解决。但是这个题有一点问题。就是这个图并不一定是联通的。所以不论以哪一个节点作为起点都是不能保证的。因此舍弃Spfa,观察数据发现N≤600非常的小,完全可以考虑Floyed,使用弗洛伊德的判断负环的方式就是看有没有Dist[i][i]!=0,然后弗洛伊德怎么解决问题了呢?
因为图并不是联通的,但是只要每一个强连通分量合法就可以了,于是我们考虑Tarjan缩点,然后对于每一个强联通分量分别求解。
在三重循环的过程中判断i,j,k是不是都属于一个强连通分量,然后就可以有一个小小的优化。
缩完点之后发现剩下的就是连接每一个联通块的零权边,对答案并没有影响,只会影响关系,并且我们设的Dist[i][j]表示的是i,j的最大差值,于是就可以寻找每一个强联通分量里面的最大值。并且每一个强联通分量在数值上没有关系,因此将答案直接累加即可,最后输出答案加上强连通分量的数量。
1 | // luogu-judger-enable-o2 |
最后发现弗洛伊德跑还是比较慢,最后加了很多register和inline才勉强卡过去。后来知道有一个非常神奇的深搜版Spfa,应该是可以更好地解决这个问题的。
v1.5.2