算法导论 25.3 Johnson算法

一,Johnson算法的思想

        如果图G中所有的边权重均为非负值,通过对每个结点进行一次Dijkstra算法来找到所有结点对之间的最短路径,如果图G中有负值的边但没有权重为负值的环路,就计算出一组新的非负权重值,并按同样的方法计算。

二,新权重的确定

        我们定义新权重w'(u,v)=w(u,v)+h(u)-h(v),满足两个性质:一是对于所有结点对(u,v),路径p是使用原权重函数w时从结点u到v的一条最短路径,当且仅当p是在使用新权重函数w'时从u到v的一条最短路径,二是新权重为非负值。

三,Johnson算法介绍

        准备阶段:一张赋值有向图

        算法过程:我们在图G中增加一个新结点S,并让其与其他结点相连,形成一幅新图G',对G'进行Bellman-Ford算法计算从S到各结点的最短路径h,删除结点S,然后根据新权重确定公式:w'(u,v)=w(u,v)+h(u)-h(v)对原图的权重进行修改,使得权重都为正,然后对每个结点进行一次Dijkstra算法找到结点对的最短路径。

四,Johnson算法的伪代码

JOHNSON(G,w)

1. compute G',where G'.V=G.V∪{s},G'.E=G.E∪{(s,v):v∈G.V},w(s,v)=0 for all v∈G.V

2. if BELLMAN_FORD(G',w,s)==FALSE

3.     print"the input graph contains a negative-weight cycle"

4. else for each vertex v∈G'.V

5.             set h(v) to the value of δ(s,v) computed by the Bellman-Ford algorithm

6.         for each edge(u,v)∈G'.E

7.             w'(u,v)=w(u,v)+h(u)-h(v)

8.             let D=(duv)be a new n*n matrix

9.             for each vertex u∈G.V

10.                run DIJKSTRA(G,w',u) to compute δ'(u,v) for all v∈G.V

11.                for each vertex v∈G.V

12.                    duv=δ'(u,v)+h(v)-h(u)

13. return D

第1行中,在图G中加入结点S,并让S到各结点的权重为0;第2行中,用Bellman-Ford算法计算S到各结点的最短路径,如果返回false,说明有负环,如果为true,继续下面的语句;第4-12行中,有四个循环,第一个循环将每个结点的h值算出,也就是前面BF算法算出来的最短路径,第二个循环将每条边的权重根据新权重确定方法重新赋值,随后创建最终的最短路径权重矩阵D,第三个循环对每个结点进行一次Dijkstra算法计算每个结点到其他所有结点的最短路径,并让duv等于算出来的最短路径减去前面加上的h(u)-h(v);第13行返回最短路径权重矩阵D

五,Johnson算法的复杂度

时间复杂度:O(V²lgV+VE)

六,Johnson算法的代码

这里用了二维数组表示矩阵

int ** Johnson_Algo(Graph * graph)
{
	int ** D;
	D = (int **)malloc(NODESIZE * sizeof(int *));
	for (int i = 0; i < NODESIZE; i++)
	{
		D[i] = (int *)malloc(NODESIZE * sizeof(int));
	}
	Graph *g = buildGraph_Johnson(graph);
	if (Bellman_Ford_Algo(g, g->getNodeList().back()) == false)
	{
		cout << "存在负边环";
	}
	else {
		for (int i = 0; i < g->getNodeList().size()-1; i++)
		{
			g->getNodeList()[i]->setH(g->getNodeList()[i]->getD());

		}
		for (int j = 0; j < g->getEdgeList().size(); j++)
		{
			Edge *edge = g->getEdgeList()[j];
			edge->setW(edge->getW() + edge->getStartNode()->getH() - edge->getEndNode()->getH());
		}

		for (int u = 0; u < graph->getNodeList().size(); u++)
		{
			Dijkstra_Algo(graph, graph->getNodeList()[u]);
			for (int v = 0; v < graph->getNodeList().size(); v++)
			{
				D[u][v] = graph->getNodeList()[v]->getD()+ graph->getNodeList()[v]->getH()- graph->getNodeList()[u]->getH();
			}
		}
	}
	return D;
}

你可能感兴趣的:(算法导论,数据结构,算法导论)