zoukankan      html  css  js  c++  java
  • 再谈Bellman-Ford

    这几天学校女生节,挺累的,感觉还是挺好玩的,前几天看了一下最短路,Bellman-fort算法果然比较厉害,今天又参考了刘汝佳的两本书,有了一点新的认识。

    废话不说,先上代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int maxn = 1000;
    
    struct Edge
    {
        int from,to;
        int dist;
    };
    
    struct BellmanFord
    {
        int n,m;
        vector<Edge> edges;
        vector<int> G[maxn];
        bool inq[maxn];
        int d[maxn];
        int p[maxn];
        int cnt[maxn];
    
        void init(int n)
        {
            this->n = n;
            for(int i=0; i<n; i++) G[i].clear();
            edges.clear();
        }
    
        void AddEdge(int from,int to,int dist)
        {
            edges.push_back((Edge)
            {
                from,to,dist
            });
            m = edges.size();
            G[from].push_back(m-1);
        }
    
        bool negativeCycle(int s)
        {
            queue<int> Q;
            memset(inq,0,sizeof(inq));
            memset(cnt,0,sizeof(cnt));
    
            for(int i=0; i<n; i++)
            {
                d[i] = INF;
            }
    
            d[s] = 0;
            inq[s] = true;
            Q.push(s);
    
            while(!Q.empty())
            {
                int u = Q.front();
                Q.pop();
                inq[u] = false;
                for(int i=0; i<G[u].size(); i++)
                {
                    Edge& e = edges[G[u][i]];
                    if(d[u]<INF&&d[e.to]>d[u]+e.dist)
                    {
                        d[e.to] = d[u] + e.dist;
                        p[e.to] = G[u][i];
                        if(!inq[e.to])
                        {
                            Q.push(e.to);
                            inq[e.to] = true;
                            if(++cnt[e.to]>n)
                                return false;
                        }
                    }
                }
            }
            return true;
        }
    
    };
    
    struct BellmanFord
    {
        int n,m;
        vector<Edge> edges;
        vector<int> G[maxn];
        bool inq[maxn];
        int d[maxn];
        int p[maxn];
        int cnt[maxn];
    
        void init(int n)
        {
            this->n = n;
            for(int i=0; i<n; i++) G[i].clear();
            edges.clear();
        }
    
        void AddEdge(int from,int to,int dist)
        {
            edges.push_back((Edge)
            {
                from,to,dist
            });
            m = edges.size();
            G[from].push_back(m-1);
        }
    
        bool negativeCycle()
        {
            queue<int> Q;
            memset(inq,0,sizeof(inq));
            memset(cnt,0,sizeof(cnt));
            for(int i=0; i<n; i++)
            {
                d[i] = 0;
                inq[0] = true;
                Q.push(i);
            }
    
            while(!Q.empty())
            {
                int u = Q.front();
                Q.pop();
                inq[u] = false;
                for(int i=0; i<G[u].size(); i++)
                {
                    Edge& e = edges[G[u][i]];
                    if(d[e.to]>d[u]+e.dist)
                    {
                        d[e.to] = d[u] + e.dist;
                        p[e.to] = G[u][i];
                        if(!inq[e.to]) {
                            Q.push(e.to);
                            inq[e.to] = true;
                            if(++cnt[e.to]>n)
                                return true;
                        }
                    }
                }
            }
            return false;
        }
    
    };
    View Code

     

    第一个Bellman-Ford算法是紫书上的;

    解析:

    1、起点入队列

    2、初始化点到起点的距离是INF;

    3、和Dijkstra相比,每个结点可以多次加入(如果有负环,那么这个结点是可以多次松弛的,一旦次数无穷就说明了这的确是个负环);

    4、因为是从起点出发的,然后在搜索邻接表,没有找到负环,只能说明,从起点到不了负环,但是可能是有负环的。没有负环,最短路数组 d 是正确可用的。

    第二个Bellman-Ford算法是白书上的;

    解析:

    1、Bellman-Ford 算法一个重要应用就是判负环,上面的一个起点入队列,就要改成所有点入队列。

    2、初始化 d 数组为 0:

      可以从第二图中,有一个负环,但是从 0 ,无法松弛;但是,在队列中,从 1 开始搜索的时候,还是可以松弛,并且找到这个负环;然后由于每个结点之前都入过队列,就能保证找到那个负环。

  • 相关阅读:
    星际之门(一)
    数组及指针效率
    centos directory server
    today reading notes
    lamp apache配置虚拟主机
    CentOS7 yum lamp 虚拟主机配置 lamp各组件简单影响性能的参数调整--for 一定的环境需求
    CentOS7 lamp安装 centoOS6 lamp
    查看实时公网ip
    CentOS6无法本地登陆,ssh远程登陆没问题
    tomcat root dir log 配置
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6123476.html
Copyright © 2011-2022 走看看