码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-04-07 21:52:44      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:次短路   dijkstra算法   

利用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 100000000
typedef 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]);
}


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

标签:次短路   dijkstra算法   

原文地址:http://blog.csdn.net/u014800748/article/details/44923679

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!