[POJ 3169]

Layout

差分约束系统。

有n只牛,每只牛i对应x轴上一点di,对于i < j,有di <= dj。存在ml个关系di >= dj – k,其中i < j;又存在md个关系di <= dj - k,其中i < j。要求d[n] - d[1]最大值。若关系无法满足,输出-1;若最大值为无穷,输出-2。 由于题目所求的是限制约束下的最大值,也即需要取大于等于号建立差分约束系统,那么3种边分别有: dj >= di
di + k >= dj
dj – k >= di

初始化除d1外的di值为无穷大,便可以用SPFA求解了。每次当 di + k < dj 时,进行松弛 dj = di + k。 但是……用栈跑SPFA时却无限WA。换成队列一下就AC了。找到了原始数据后又看了别人的程序,最后发现问题出在了判负环上。 基于队列的SPFA是用入栈次数>n来判断是否存在负环的,而姜碧野的《SPFA算法的优化与应用》中深搜的SPFA通过节点是否在栈中判负环是针对递归实现的。而我写的是基于栈的非递归SPFA,用的还是根据入栈次数>n判负环,但却发现很易出现误判。猜测由于深搜SPFA可以说是“盲目”推进的,也即有可能过多地沿回边更新,而导致入栈次数超过n,但实际却不存在负环。例如下图的例子:

435_0

最后的解是d[1..5] = {0, 4, 6, 10, 3},其中结点5的入栈次数高达8次,但仍是无负环的。

在这题中,如果改变邻接表中边的顺序,让深搜SPFA尽量往图的深处推进,就能使用入栈次数来正确地判断负环了。可惜没有找到通用的严格证明……

结论就是:下次还是老老实实用队列判负环吧……