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 }

 

 

 

 

 -----------------------------------

 

 

 

只有不断学习才能进步!

 

转载于:https://www.cnblogs.com/wenbao/p/7436546.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值