求出单源的第二短路径。
次短路径可以看作是k短路径问题的一种特殊情况,求k短路径有Yen算法等较为复杂的方法,对于次短路径,可以有更为简易的方法。下面介绍一种求两个顶点之间次短路径的解法。
我们要对一个有向赋权图(无向图每条边可以看作两条相反的有向边)的顶点S到T之间求次短路径,首先应求出S的单源最短路径。遍历有向图,标记出可以在最短路径上的边,加入集合K。然后枚举删除集合K中每条边,求从S到T的最短路径,记录每次求出的路径长度值,其最小值就是次短路径的长度。
在这里我们以为次短路径长度可以等于最短路径长度,如果想等,也可以看作是从S到T有不止一条最短路径。如果我们规定求从S到T大于最短路径长度的次短路径,则答案就是每次删边后大于原最短路径的S到T的最短路径长度的最小值。
在这里,删除一条边反复调用dj算法,可以过于复杂一点,在这里还有一种办法就是,求出单源最短路径之后,维持一个t_dis数组求出的是不包含最短路径前驱点的第二短路径的长度,求出此点后,枚举每一个最短路径的边i,j,点j次短路径长度=min(t_dis(i)+dis(i,j),t_dis(j))
1 #include <stdio.h>
2 const int MAXN = 1000+5;
3 const int INF = 999999999;
4
5 int g[MAXN][MAXN];
6 int dis[MAXN];
7 int pre[MAXN];
8 int ord[MAXN];
9 int ts_dis[MAXN];
10 int s_dis[MAXN];
11 int m;
12
13 void dijkstra()
14 {
15 bool used[MAXN] = {false};
16 for (int i = 0; i < m; i++) {
17 dis[i] = INF;
18 }
19 dis[0] = 0;
20 pre[0] = INF;
21 for (int i = 0; i < m; i++) {
22 int k = -1;
23 int min_dis = INF;
24 for (int j = 0; j < m; j++) {
25 if (false == used[j] && dis[j] < min_dis) {
26 k = j;
27 min_dis = dis[j];
28 }
29 }
30 if (k == -1) {
31 break;
32 }
33 ord[i] = k;
34 used[k] = true;
35 for (int j = 0; j < m; j++) {
36 if (false == used[j] && min_dis + g[k][j] < dis[j]) {
37 dis[j] = min_dis + g[k][j];
38 pre[j] = k;
39 }
40 }
41 }
42 }
43
44 void second_dijkstra()
45 {
46 for (int i = 0; i < m; i++) {
47 int min_dis = INF;
48 for (int j = 0; j < m; j++) {
49 if (j != pre[i] && dis[j] + g[j][i] < min_dis) {
50 min_dis = dis[j] + g[j][i];
51 }
52 }
53 ts_dis[i] = min_dis;
54 }
55 s_dis[ord[0]] = ts_dis[ord[0]];
56 for (int i = 1; i < m; i++) {
57 if (ts_dis[ord[i]] < s_dis[pre[ord[i]]] + g[pre[ord[i]]][ord[i]]) {
58 s_dis[ord[i]] = ts_dis[ord[i]];
59 } else {
60 s_dis[ord[i]] = s_dis[pre[ord[i]]] + g[pre[ord[i]]][ord[i]];
61 }
62 }
63 }
64
65 int main()
66 {
67 while (EOF != scanf("%d", &m)) {
68 for (int i = 0; i < m; i++) {
69 for (int j = 0; j < m; j++) {
70 g[i][j] = INF;
71 }
72 }
73 for (int i = 0; i < m; i++) {
74 int n;
75 scanf("%d", &n);
76 for (int j = 0; j < n; j++) {
77 int a, w;
78 scanf("%d %d", &a, &w);
79 g[i][a-1] = w;
80 }
81 }
82 dijkstra();
83 second_dijkstra();
84 printf("%d\n", s_dis[m-1]);
85 }
86 return 0;
87 }

浙公网安备 33010602011771号