hdu4889 spfa(造数据卡spfa

来源:互联网 发布:最优化计算方法课后题 编辑:程序博客网 时间:2024/06/05 02:57

题目是给了你一个spfa+slf优化的程序,然后,让你造个数据卡掉他,

其实那个slf优化根本不算是优化,只是在某些图上可能会更好,但是可以通过直接构造图将其由原本spfa最坏nm的复杂度卡成2^n复杂度



至于具体的,这题是曹圣 (http://blog.csdn.net/jinzhao1994) 给我讲的,他那里写的很详细,我就直接copy了






在这个图中,我们设计算从i到n的最短路所需要的运算次数为f(i),则对于奇数号点p,如1,3,..,n,会把p+1放到队尾,把p+2放到队首,因为p+2在队首,所以会先从p+2开始,又因为后边所有的边都是非正的,所以他们不会小于p+2,即他们也会放到队首。这样我们就先计算了以下从p+2出发的一次最短路,然后在从p+1到p+2,更新了p+2的值,又重新计算了一次从p+2出发的一次最短路。这样我们可以得出f(i)>2*f(i+2),这个递归式显然是指数增长的,即只需30对点,就可以让它的复杂度增长到2^30。

过这道题的代码是这样的..无须考虑输入数据...

#include<iostream>#include<cstdio>using namespace std;const int T = 30;int main(){int c;while (scanf("%d",&c)!=EOF){int n , m , i ;n = T * 2 + 1;m = T * 3;printf("%d %d\n",n,m);for (int i = 0 ; i <T ; i ++)printf("%d %d %d\n",i * 2 + 1 , i * 2 + 2 , 0);for (int i = 0 ; i <T ; i ++)printf("%d %d %d\n",i * 2 + 2 , i * 2 + 3 , - ( 1 << T - i )); for (int i = 0 ; i <T ; i ++)printf("%d %d %d\n",i * 2  + 1 ,  i * 2 + 3 , -( 1 << T - i - 1 ));}}

究其原因,要从SPFA是Bellman-ford的优化说起。在n个点m条边的图中,Bellman-ford的复杂度是n*m,依次对每条边进行松弛操作,重复这个操作n-1次后则一定得到最短路,如果还能继续松弛,则有负环。这是因为最长的没有环路的路,也只不过是n个点n-1条边构成的,所以松弛n-1次一定能得到最短路。

SPFA的意义在于,如果一个点上次没有被松弛过,那么下次就不会从这个点开始松弛。每次把被松弛过的点加入到队列中,就可以忽略掉没有被松弛过的点。

但是最外层的循环还是n-1次..如果把被松弛的点放到前边,他相当于没有进行完这一轮松弛,就开始了一些其他的操作。但是这些其他的操作可能是无用的,因为这些操作的起始点可能还会被这一轮松弛更新。

所以传统的SPFA的复杂度不会超过n*m,并且每个点都不会第n次入队。但是slf优化...其实就不是个优化..它丢掉了一轮一轮松弛的这个特性..导致复杂度可能呈指数级上升。


以上来自jinzhao1994

就是酱紫。。。><其实我自己这次也是才知道,btw提一句,晚上的时候。。。给某梁学妹说这个题。。。被10min秒杀了,,果然厉害啊唔。。。还得努力啊。。。


0 0