标签:
恶心的输入恶心的题面啊。。。这道题学到的东西还是蛮多的
Description。。有向图。。边权有两个:1.费用, 2.长度。要求找出S到T花费最小的路。一定要是花费最小。。。。在花费最小的情况下输出路径长度的最小值。。然后边权可以为负。。不保证S到T一定有一条路。。同时点a到点b之间可能有多条路。。。
总之就是。。S不能到T输出VOID,S到T的路径上有负环(即没有最小值)输出UNBOUND。。其他有解情况输出最小花费和最小路径长度。。
唔首先输入的时候我们可以干一个事情就是只保留一条最小的边。。。
然后本道题的考察点。。ST路径上有没有负环。。
我大概看到了两种做法。。
首先。。如果负环上的点可以到达T点。即ST路径上有这个点那最终的结果就会受负环影响。。
所以第一种就是。。
1.我们照常spfa。。然后记入队次数。。然后把入队次数大于总点数n的搜一下能不能到达T点。。只要有任意一个点可以到达T点我们就输出UNBOUND。。
然后spfa怎么break呢。。我们把入队次数大于n改成大于n + 几.。这样就可以保证所有的负环上的点都入队了n次以上。。比如我们把边界设置成n + 5。。
然后VOID直接判dis[T]为不为INF。。没有负环也有解就输出。。
第二种方法是酱似儿的。
2.我们把所有的边反向然后从T点开始搜。。dfsbfs随意。。然后把不能到达T点的点都筛去。。现在原问题就相当于在整个新图上判定负环了。。跑spfa就好了。。
然后怎么删点。。我看到了两种做法。。一个是vector直接erase。。。。【2333333建议不要用vector2333333容易被卡常233邻接表大法好】
一个是邻接表。然后是判断哪些点能到达。。重新再建一遍图。。重新。。
唔其实我有个想法但是我没写这个想法。。我就是随便yy了一下。。就是。。dfs/bfs标记完为什么要删边呢????扩展节点的时候直接判一下此点能不能到达T点然后如果不能的话就直接continue不需要加入队列了。。为什么网上都没有人写。。。。interesting。。
然后网上有三种做法。。我搬来好了。。
1:邻接表(前向星)存图,用的楼上第一种方法解决问题,然后每次都用的dfs。spfa的队列用了滚动队列优化。896k。32ms。
2:vector实现,dfs标记删点。940k。47ms。。。vector卡常数啊。。。。。
3.邻接表(前向星)。。然后也是搜索标记删点。。用的bfs。然后是重新建了一遍图。。这个方法除了储存方法和搜索方式不同外和第二个没有什么区别。。
但是看人家的时空复杂度。1212k。0ms。
0ms。0ms。0ms。0ms!!!!!!!!
我觉得2应该是被vector拖慢的速度233然后bfs比dfs快然后所以相当空间换时间23333
第一个一看效率应该是没下面两个效率高的。。嗯。。。。。。
呐。。。个人原因就不放我的渣代码了TATAT
但是为了证明我写了:
唔。。就酱。。。。。。。
------------------------------------------------------
POJ 2679 Adventurous Driving | SPFA + 判定负环
标签:
原文地址:http://www.cnblogs.com/shadyqwq-juruo/p/5746149.html