天天看点

贪心算法——单源最短路径 dijkstra

关于单源最短路径的问题非常典型,这里没有给出分析与证明,仅仅给出了实现。

需要指出的是,许多实现仅给出了最短路径的长度,而没有给出“最短路径”,这里用给出了实现。

如程序中那样,定义一个数组p[N],其中p[i]代表“起始点v到顶点i的最短路径中,除i本身的最后一个顶点”,即着这条路径上i的前驱顶点,这个顶点随着“更多顶点的最短路径被求出”这个过程而变化。

当求出v到所有顶点的最短路径以后,同时也求出了最终的p[N]。于是可以按下列回溯的方法来求出每条最短路径序列:

对于顶点j,在其最短路径上其前驱pre = p[j],i=<pre<n且pre!=j,说明“到顶点j的最短路径”是基于“到顶点pre的最短路径”的,这样一直回溯,直到pre=v(单源点),这些pre值就构成了最短路径序列。

1 #include <iostream>

2 using namespace std;

3 #define N 5

4 #define MAX 65535

5 int g[N][N];

6 void min_path(int v,long *d,int *p)

7 {

8 int i = 0;

9 int j = 0;

10 bool s[N]={false};

11 for(i=0;i<N;i++)

12 for(j=0;j<N;j++)

13 if(g[i][j] == -1)

14 g[i][j] = 65536;

15 for(i = 0;i<N;i++)

16 {

17 d[i] = g[v][i];

18 if(d[i] == MAX)

19 p[i] = 0;

20 else

21 p[i] = v;

22 }

23

24 s[v] = true;

25 d[v] = 0;

26 p[v] = 0;

27

28 int k = 0;

29 for(i = 0 ;i<N;i++)

30 {

31 int min = 65535;

32 for(j = 0 ;j<N;j++)

33 {

34 if(j != v && s[j] == false)

35 {

36 if(d[j]<=min)

37 {

38 min = d[j];

39 k = j;//k是V集合中具有最短“特殊路径的顶点”,所谓特殊路径即是从顶点v到k只经过U中的顶

点。

40 }

41 }

42 }

43 s[k] = true;//将k从V集合中并入到U集合中

44 for(j=0;j<N;j++)

45 {

46 if(s[j]==false && d[j]>d[k]+g[k][j])

47 {

48 d[j] = d[k] + g[k][j];//更新其他在V中的顶点的最短距离。

49 p[j] = k;

50 }

51 }

52 }

53 }

54 int main()

55 {

56 long d[N];

57 int p[N];//p[i]代表到达顶点i的最短路径的前驱节点,随着路径变化而变化

58 int i = 0;

59 for(i = 0;i<N;i++)

60 {

61 for(int j = 0;j<N;j++)

62 cin>>g[i][j];

63 }

64 min_path(0,d,p);

65 for( i =0;i<N;i++)

66 cout << d[i] << " ";

67 cout << endl;

68 //输出每条最短路径

69 for(i = 0;i<N;i++)

70 {

71 //if(i != 0)

72 {

73 int pre = p[i];

74 while(pre!=0)

75 {

76 cout << pre << " ";

77 pre = p[pre];

78 }

79 cout << endl;

80 }

81 }

82 }

继续阅读