次短路问题
题意:N 个点,R 条边,问从点 1 到点 N 的次短路为多少
解法:首先明白次短路的计算方法:
到某个定点 v 的次短路要么为到定点 u 的最短路加上边 (u,v)的长度;要么为到定点 u 的次短路加上边(u,v)长度。
对于第一种情况讨论的是在松弛时没有松弛的情况,即当 dist[u] > dist[v] + cost(u,v) 时,仍然选择dist[u]。
第二种情况比较简单,已经是次短路了,加上一条直接的边也不会更优。
1 struct Edge { 2 int to, weight; 3 Edge(int to, int weight) : to(to), weight(weight) {} 4 }; 5 vector<vector<Edge> > G(MAXN); //更快 6 struct Dijkstra { //打包在Dijkstra中 7 int n, m; 8 bool done[MAXN]; 9 int dist[MAXN]; //最短路 10 int dist2[MAXN]; //次短路 11 int p[MAXN]; 12 Dijkstra(int n) : n(n) { 13 for (int i = 1; i <= n; i++) G[i].clear(); 14 } 15 void AddEdge(int from, int to, int weight) { 16 G[from].push_back(Edge(to, weight)); //保存from出发的边 17 } 18 void dijkstra(int s) { 19 priority_queue<pii, vector<pii>, greater<pii> > Q; 20 memset(dist, 0x7f, sizeof(dist)); //初始化为无穷大 21 memset(dist2, 0x7f, sizeof(dist2)); 22 memset(done, false, sizeof(done)); 23 24 dist[s] = 0; 25 Q.push(pii(0, s)); // pii (dist ,u) 26 while (!Q.empty()) { 27 pii P = Q.top(); 28 Q.pop(); 29 int d = P.first, u = P.second; 30 if (dist2[u] < d) continue; 31 for (int i = 0; i < G[u].size(); i++) { 32 Edge& e = G[u][i]; 33 int v = e.to, w = e.weight; 34 int d2 = d + w; 35 if (dist[v] > d2) { 36 swap(dist[v], d2); // d2此时为次短路 37 Q.push(pii(dist[v], v)); 38 } 39 if (dist2[v] > d2 && dist[v] < d2) { 40 dist2[v] = d2; 41 Q.push(pii(dist2[v], v)); 42 } 43 } 44 } 45 } 46 }; 47 int N, R; 48 int main() { 49 // freopen("input.txt", "r", stdin); 50 N = READ(), R = READ(); 51 Dijkstra Men(N); 52 int u, v, w; 53 REP(i, 1, R) { 54 u = READ(), v = READ(), w = READ(); 55 Men.AddEdge(u, v, w); 56 Men.AddEdge(v, u, w); 57 } 58 Men.dijkstra(1); 59 cout << Men.dist2[N] << endl; 60 return 0; 61 }