次短路问题

题意: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 }

 

转载于:https://www.cnblogs.com/romaLzhih/p/11442793.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值