zoukankan      html  css  js  c++  java
  • 【图论】BellmanFord算法

    适用于任何权的图,负权也可以做。假如从s出发的子图中存在负环,则算法会报告发现负环,否则会正确求出最短路。

    松弛操作

    一种基于松弛(relax)操作的最短路算法。

    第i轮松弛(每条边使用一次)后,从节点s出发的经过<=i条边的到达每个节点的最短路已经找到。假如存在最短路,则最多经过n-1条边。所以假如一条边被松弛了n次,则不存在(从s到达v的)最短路。

    BellmanFord算法

    队列优化

    成功入队的才是相比上一轮松弛有变化的点,其他的点不需要松弛。

    返回值表示是否不存在从s出发能到达的负环。

    namespace BellmanFord {
    
        const int MAXN = 2e5 + 10;
    
        int n;
        vector<pii> G[MAXN];
    
        ll dis[MAXN];
        int cnt[MAXN];
        bool vis[MAXN];
    
        queue<int> Q;
    
        bool bellmanford(int s) {
            fill(dis + 1, dis + 1 + n, LINF);
            fill(cnt + 1, cnt + 1 + n, 0);
            fill(vis + 1, vis + 1 + n, 0);
            while(!Q.empty())
                Q.pop();
            dis[s] = 0;
            vis[s] = 1;
            Q.push(s);
            while(!Q.empty()) {
                int u = Q.front();
                Q.pop();
                vis[u] = 0;
                ++cnt[u];
                if(cnt[u] == n)
                    return false;
                for(pii &p : G[u]) {
                    int v = p.first;
                    int w = p.second;
                    if(dis[v] <= dis[u] + w)
                        continue;
                    dis[v] = dis[u] + w;
                    if(!vis[v]) {
                        vis[v] = 1;
                        Q.push(v);
                    }
                }
            }
            return true;
        }
    
    }
    

    乱优化

    除了队列优化以外,其他的奇奇怪怪的优化完全不知道其道理何在。

    栈优化

    这个也是改变了点松弛的顺序,不再满足每一轮松弛原本的定义,所以n轮松弛不一定够(即超过n次松弛仍然可能不是负环),最差复杂度为指数级。

    优先队列优化

    这个也是改变了点松弛的顺序,不再满足每一轮松弛原本的定义,所以n轮松弛不一定够(即超过n次松弛仍然可能不是负环),最差复杂度为指数级。

    LLL优化

    将普通队列换成双端队列,每次将入队结点距离和队内距离平均值比较,如果更大则插入至队尾,否则插入队首。

    SLF优化

    将普通队列换成双端队列,每次将入队结点距离和队首比较,如果更大则插入至队尾,否则插入队首。

  • 相关阅读:
    Django学习案例一(blog):四. 使用Admin
    Django学习案例一(blog):三. 模型生成数据
    Django学习案例一(blog):二. 连接数据库
    连接Xively云
    undefined reference to `_sbrk', `_write', `_lseek', `_read'
    Android manifest
    关于android socket出现at java.net.DatagramSocket java.net.BindException at libcore.io.IoBridge.bind(IoBridge.java:89)等waring
    virtual box Failed to load unit ""pgm" 的error
    Lwip lwip_recvfrom函数一个数据包不能分多次读取。
    获取Window下的文件缩略图
  • 原文地址:https://www.cnblogs.com/purinliang/p/14388016.html
Copyright © 2011-2022 走看看