1 /*
2 *解题报告
3 [转: http://hi.baidu.com/lewutian/blog/item/7986c62c4aa412e18a1399bb.html ]
4 本人在POJ上做过次小生成树的问题。当时的解决思路是把最小生成树里面的边逐个去掉,
5 而计算现在的最小生成树。证明很简单,在此略去。
6
7 可是现在解决次短路问题也采用这样的思路就会非常麻烦。SPFA一次的时间复杂度
8 大约是O(2n),枚举最短路的边是O(r)级别的,这样看来最坏情况下的
9 时间复杂度就会有O(2nr),将近10亿。
10 就算是O(r)太过悲观的话,想在2秒内出解也比较悬。
11
12 分析一下状况,次短路不可能与最短路完全重合,那么就一定会有一段比较绕路。
13 绕路的地方不可能超过两处,那样就有一条路短于这条路而长于最短路,矛盾。
14 因此可以对所有的边加以枚举。
15
16 首先用Dijkstra或SPFA以原点和终点为源分别做一次单源最短路,
17 并把答案存在dist_0和dist_n两个数组中。那么,对于任何一条边(i, j),
18 下面的二者之一就有可能是次短路的长:
19
20 dist_0[i] + len(i, j) + dist_n[j] 和 dist_0[j] + len(i, j) + dist_n[i]
21
22 注意,如果其中一个的长度等于最短路的长度(即dist_n[0]),就一定不能选,
23 因为这违反次短路的定义。两个都要枚举,因为可能有其中一个等于最短路的长,
24 如果只取较小的值另外一个就废掉了。
25 *
26 *
27 */
28 #include <cstdio>
29 #include <cstring>
30 using namespace std;
31
32 const int maxn = 5000 + 10;
33 const int maxr = 100000 + 10;
34 const int inf = 10000000;
35
36 int n, r, edgeNum = 0;
37 int dist[2][maxn];
38 bool vis[maxn] = {};
39
40 struct SData{
41 int v, w;
42 SData *next;
43 };
44 SData *adj[maxn], edge[2*maxr];
45
46
47 void insert(int u, int v, int w){
48 edge[edgeNum].next = NULL;
49 edge[edgeNum].v = v;
50 edge[edgeNum].w = w;
51 if(adj[u] == NULL)
52 adj[u] = &edge[edgeNum];
53 else{
54 edge[edgeNum].next = adj[u];
55 adj[u] = &edge[edgeNum];
56 }
57 edgeNum++;
58 }
59
60 //s:起点
61 //a:数组下标,起点为1时a=0;起点为0时a=1
62 void Dijkstra(int s, int a){
63 memset(vis, 0, sizeof(vis));
64 for(int i=1; i<=n; i++)
65 dist[a][i] = inf;
66 dist[a][s] = 0;
67
68 int cur = s, mind=inf, minv;
69 vis[s] = 1;
70 SData *p;
71 while(true){
72 p = adj[cur];
73 while(p != NULL){
74 if(!vis[p->v] && dist[a][p->v] > dist[a][cur] + p->w){
75 dist[a][p->v] = dist[a][cur] + p->w;
76 }
77 p = p->next;
78 }
79
80 mind = inf;
81 for(int i=1; i<=n; i++){
82 if(!vis[i] && dist[a][i] < mind){
83 mind = dist[a][i];
84 minv = i;
85 }
86 }
87
88 if(mind == inf) break;
89
90 cur = minv;
91 vis[cur] = 1;
92 }
93 }
94
95
96 int main(){
97 scanf("%d%d", &n, &r);
98 int u, v, w;
99 for(int i=0; i<r; i++){
100 scanf("%d %d %d", &u, &v, &w);
101 insert(u, v, w);
102 insert(v, u, w);
103 }
104
105 //shortest path
106 Dijkstra(1, 0);
107 Dijkstra(n, 1);
108
109 //answer
110 int min=inf, lastMin, tmp;
111 SData *p;
112 for(int i=1; i<=n; i++){
113 p = adj[i];
114 while(p!=NULL){
115 tmp = dist[0][i] + p->w + dist[1][p->v];
116 if(tmp < min){
117 lastMin = min;
118 min = tmp;
119 }
120 else if(tmp > min && tmp < lastMin)
121 lastMin = tmp;
122
123 tmp = dist[1][i] + p->w + dist[0][p->v];
124 if(tmp < min){
125 lastMin = min;
126 min = tmp;
127 }
128 else if(tmp > min && tmp < lastMin)
129 lastMin = tmp;
130 p = p->next;
131 }
132 }
133 printf("%d\n", lastMin);
134
135 return 0;
136 }