既昨天搞定了双向BFS对地图类的搜索优化,今天思考了一下双向Dijkstra。
Dijkstra的实质仍然是贪心。如果给定了起点和终点,能否同时进行Dijkstra,相遇时获得最短路呢?
简单思考,最短路加最短路,好像是对的。好吧,看下面这个图:
如果求A,B最短路,则先从A选择最短边6,到达C点,标记C点。(实际是松弛Relax,不过这么说比较好理解)。然后B点选择最短路6(终点则走反向),到达C点,标记C点。获得最短路12。这显然是错的,因为还是8这条最短路。
解决办法也很简单。每次试图寻找最短路时,判断未标记的点是否被反向标记。如果被标记则将总距离记录下来。在标记相遇时取最小距离则是最短路。当然,我不会证明。不过根据测试来看,是没错的= =。
双向的另一个问题是边的处理。如果图中有双向边,用邻接表的话则要记录两组边。一组正向,一组反向。如果是邻接矩阵就不用那么麻烦了,不过点数过多的情况下是开不了那么大的数组的。这是缺点。
不说废话了。找了以前做的一道经典的题,POJ 3159 Candies 。30000点,150000边求最短路。之前用SPFA和Dijkstra都A过了,今天一边尝试双向Dijkstra一边WA。搞了一天总算是A了。贴代码:双向Dijkstra,610MS
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxV=30030;
const int maxE=150010;
int first[2][maxV],vv[2][maxE],ww[2][maxE],nxt[2][maxE]; // 邻接表
bool vis[2][maxV]; //