wenbao与次短路
每次更新最短路的时候顺便更新次短路 存在d 满足 dis[i] < d&& d < dis2[i] 更新dis2[i] = d
也可以求两次最短路(s到t,t到s),然后枚举每条不包含在最短路上的边(次短路一定是替换了最短路的一条边)
既然是次短路,那么求解k短路的A*算法当然也可以
亲测A*相对而言快一点
----------------------------------------
http://poj.org/problem?id=3255
1 #include <iostream> 2 #include <queue> 3 #include <vector> 4 using namespace std; 5 #define pri pair<int, int> 6 const int INF = 1e9; 7 const int maxn = 5009; 8 vector<pri> v[maxn]; 9 int n, r, x, y, z, dis[maxn], dis2[maxn]; 10 void d(){ 11 priority_queue<pri, vector<pri>, greater<pri> > pq; 12 pq.push(pri(0,1)); //pri默认以first排序 13 for(int i = 0; i <= n; ++i) dis[i] = INF, dis2[i] = INF; 14 dis[1] = 0; 15 while(!pq.empty()){ 16 pri b = pq.top(); 17 pq.pop(); 18 int xx = b.second, yy = b.first; 19 if(dis2[xx] < yy) continue; 20 for(int i = 0; i < v[xx].size(); ++i){ 21 int vv = v[xx][i].first, d = yy + v[xx][i].second; 22 if(dis[vv] > d){ 23 swap(dis[vv], d); //注意是交换,不是赋值,因为dis[vv]可以更新dis2[vv] 24 pq.push(pri(dis[vv], vv)); 25 } 26 if(dis[vv] < d && dis2[vv] > d){ 27 dis2[vv] = d; 28 pq.push(pri(d, vv)); 29 } 30 } 31 } 32 printf("%d\n", dis2[n]); 33 } 34 int main(){ 35 scanf("%d%d", &n, &r); 36 for(int i = 0; i < r; ++i){ 37 scanf("%d%d%d", &x, &y, &z); 38 v[x].push_back(pri(y, z)); 39 v[y].push_back(pri(x, z)); 40 } 41 d(); 42 return 0; 43 }
两次最短路
1 #include <iostream> 2 #include <string.h> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 #define INF 1e9; 7 const int maxn = 5009; 8 int n, m, from, to, val, d1[maxn], dn[maxn]; 9 bool mark[maxn]; 10 vector<int> a[maxn]; 11 vector<int> b[maxn]; 12 void spfa(int s, int t, int T[]){ 13 for(int i = 1; i <= n; ++i) T[i] = INF; 14 T[s] = 0; 15 queue<int> q; 16 q.push(s); 17 while(!q.empty()){ 18 int k = q.front(); 19 q.pop(); 20 mark[k] = false; 21 for(int i = 0; i < a[k].size(); i++)if(T[k] + b[k][i] < T[a[k][i]]) { 22 T[a[k][i]] = T[k] + b[k][i]; 23 if(!mark[a[k][i]]){ 24 q.push(a[k][i]); 25 mark[a[k][i]] = true; 26 } 27 } 28 } 29 } 30 void solve(){ 31 int mi = INF; 32 for(int i = 1; i <= n; ++i){ 33 for(int j = 0; j < a[i].size(); ++j){ 34 int v = a[i][j], d = b[i][j]; 35 if(d1[i]+dn[v]+d > d1[n]) mi = min(mi, d1[i]+dn[v]+d); 36 } 37 } 38 printf("%d\n", mi); 39 } 40 int main(){ 41 scanf("%d%d", &n, &m); 42 for(int i = 0; i < m; i++) { 43 scanf("%d%d%d", &from, &to, &val); 44 a[from].push_back(to); 45 b[from].push_back(val); 46 a[to].push_back(from); 47 b[to].push_back(val); 48 } 49 spfa(1, n, d1); 50 spfa(n, 1, dn); 51 solve(); 52 return 0; 53 }
A*
1 #include <iostream> 2 #include <queue> 3 using namespace std; 4 5 #define INF 1e9; 6 const int maxn = 200003; 7 int n, m, to[maxn], w[maxn], pre[maxn], p[5003], index = 1, T[5003]; 8 bool mark[5003]; 9 10 struct Node{ 11 int v, dis; 12 bool operator < (const Node b) const { 13 return dis + T[v] > b.dis + T[b.v]; 14 } 15 }; 16 17 void solve(){ 18 for(int i = 1; i <= n; ++i) T[i] = INF; 19 T[n] = 0; 20 queue<int> q; 21 q.push(n); 22 while(!q.empty()){ 23 int k = q.front(); 24 q.pop(); 25 mark[k] = false; 26 for(int i = p[k]; i; i = pre[i])if(T[k] + w[i] < T[to[i]]){ 27 T[to[i]] = T[k] + w[i]; 28 if(!mark[to[i]]){ 29 q.push(to[i]); 30 mark[to[i]] = true; 31 } 32 } 33 } 34 priority_queue<Node> pq; 35 int cnt = 0; 36 Node a, b; 37 a.v = 1, a.dis = 0; 38 pq.push(a); 39 while(!pq.empty()){ 40 a = pq.top(); pq.pop(); 41 int v = a.v, dis = a.dis; 42 if(v == n){ 43 if(++cnt == 2){ 44 printf("%d\n", dis); 45 break; 46 } 47 } 48 for(int i = p[v]; i; i = pre[i]){ 49 b.v = to[i], b.dis = dis + w[i]; 50 pq.push(b); 51 } 52 } 53 } 54 55 int main(){ 56 scanf("%d%d", &n, &m); 57 int x, y, z; 58 for(int i = 0; i < m; ++i){ 59 scanf("%d%d%d", &x, &y, &z); 60 to[index] = y, w[index] = z, pre[index] = p[x], p[x] = index++; 61 to[index] = x, w[index] = z, pre[index] = p[y], p[y] = index++; 62 } 63 solve(); 64 return 0; 65 }
-----------------------------------
只有不断学习才能进步!