图论算法小结:次短路的求解

来源:互联网 发布:isofans 淘宝店 编辑:程序博客网 时间:2024/06/06 04:24

利用Dijkstra算法求解次短路

我们曾经学过利用Dijkstra算法求解最短路,但是如果要求解某一个结点的次短路该怎么做呢?实际上,我们仍然可以用Dijkstra算法来求解它。


首先来回顾一下Dijkstra算法的原理:首先把所有结点的最短距离设置为无穷大,然后令d[0]=0。接下来,每次都找到最短路已经确定的经典,更新从它出发的相邻结点的最短距离。以后我们不再考虑最短距离已经确定了的结点。


以上就是Dijkstra算法的主要过程,需要注意的一点是我们不再考虑的是“最短距离已经确定了的结点”,不要错误地理解为是更新过最短距离值的结点。因为有些结点的最短路可能需要多次更新才能最终确定。那么问题来了,如何知道哪些结点的最短距离是确定的呢?这里我们利用了一点贪心的思想,每次都取出当前距离最短的那个结点,认为它的最短路就是已经确定好的。可以证明这样的做法是正确的。这也算为什么优化版本的DIjkstra算法用到了priority_queue的原因。


那么回到主题,如何求解次短路呢?如果我们要求解起点s到终点t的次短路,那么有两种可能的情况:(1)起点s到某个顶点u的最短路+d(u,t)。(2)起点到某个顶点u的次短路+d(u,t)。因此,对于每个结点,我们记录的不仅仅是最短距离,还有次短距离,接下来用类似于Dijkstra算法不断更新这两个距离即可求出次短路了。

#define N 100000+10#define INF 100000000typedef pair<int, int>P;int n,r;struct Edge{ int to, cost; };vector<Edge>G[N];int dist[N], dist2[N];void addedge(int u, int v,int w){G[u].push_back(Edge{ v, w });G[v].push_back(Edge{ u, w });}void solve(){priority_queue<P, vector<P>, greater<P> >q;fill(dist, dist + n, INF);fill(dist2, dist2 + n, INF);dist[0] = 0;q.push(P(0, 0));while (!q.empty()){P u = q.top(); q.pop();int v = u.second, d = u.first;if (dist2[v] < d)continue;//取出的不是次短距离,抛弃for (int i = 0; i < G[v].size(); i++){Edge&e = G[v][i];int d2 = d + e.cost;if (dist[e.to]>d2)//更新最短距离{swap(dist[e.to], d2);q.push(P(dist[e.to], e.to));}if (dist2[e.to]>d2&&dist[e.to] < d2)//更新次短距离{dist2[e.to] = d2;q.push(P(dist2[e.to], e.to));}}}printf("%d\n", dist2[n - 1]);}


2 0
原创粉丝点击