图论$\cdot$最短路问题

  • Dijkstra单源最短路径算法

Dijkstra可以计算出发点到每个点的最短路,及单源最短路径(SSSP)。这一特点使得Dijkstra常常用来进行其他算法的预处理。用Dijkstra算法计算最短路的代码如下:

注:代码注释参见《算法竞赛入门经典——训练指南》(刘汝佳)

 1 struct Dijkstra{
 2     int n, m;
 3     vector<E> e;
 4     vector<int> G[maxn];
 5     bool done[maxn];
 6     int d[maxn];
 7     int p[maxn];
 8     void init(int n){
 9         this->n = n;
10         FOR(i, 0, n - 1) G[i].clear();
11         e.clear();
12     }
13     void addE(int from, int to, int dist){
14         e.pb(E(from, to, dist));
15         m = e.size();
16         G[from].pb(m - 1);
17     }
18     void dijkstra(int s){
19         priority_queue<HeapNode> Q;
20         FOR(i, 0, n - 1) d[i] = int_inf;
21         d[s] = 0;
22         clr(done, 0);
23         Q.push(HeapNode(0, s));
24         while(!Q.empty()){
25             HeapNode x = Q.top(); Q.pop();
26             int u = x.u;
27             if(done[u]) continue;
28             done[u] = 1;
29             int sz = G[u].size();
30             FOR(i, 0, sz - 1){
31                 E &y = e[G[u][i]];
32                 if(d[y.to] > d[u] + y.dist){
33                     d[y.to] = d[u] + y.dist;
34                     p[y.to] = G[u][i];
35                     Q.push(HeapNode(d[y.to], y.to));
36                 }
37             }
38         }
39     }
40 };
  •  Bellman-Ford算法

Bellman-Ford算法的一个重要应用是判负圈。在迭代$n-1$次后如果还可以进行松弛(relax)操作,说明一定存在负圈。如果采用队列实现,那么当某个结点入队了$n$次时可以判断出存在负圈,代码如下:

 1 struct Bellman_Ford{
 2     int n, m;
 3     vector<E> e;
 4     vector<int> G[maxn];
 5     bool inq[maxn];
 6     int d[maxn];
 7     int p[maxn];
 8     int cnt[maxn];
 9     void init(int n){
10         this->n = n;
11         FOR(i, 0, n - 1) G[i].clear();
12         e.clear();
13     }
14     void addE(int from, int to, int dist){
15         e.pb(E(from, to, dist));
16         m = e.size();
17         G[from].pb(m - 1);
18     }
19     bool negCyc(){
20         queue<int> Q;
21         clr(inq, 0), clr(cnt, 0);
22         FOR(i, 0, n - 1) d[i] = 0, inq[i] = 1, Q.push(i);
23         while(!Q.empty()){
24             int u = Q.front(); Q.pop();
25             inq[u] = 0;
26             int sz = G[u].size();
27             FOR(i, 0, sz - 1){
28                 E &y = e[G[u][i]];
29                 if(d[y.to] > d[u] + y.dist){
30                     d[y].to = d[u] + y.dist;
31                     p[e.to] = G[u][i];
32                     if(!inq[y.to]){
33                         Q.push(y.to);
34                         inq[y.to] = 1;
35                         if(++cnt[y.to] > n) return 1;
36                     }
37                 }
38             }
39         }
40         return 0;
41     }
42 };

 

转载于:https://www.cnblogs.com/astoninfer/p/5767118.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值