Bellman_Ford的负环

大家都知道Bellman的优化版是SPFA
但是我还是偏向于叫Bellman
这是一种重要的负环判断法(同时维护单源最短路

//这里写代码片

struct node{
    int x,y,v;
};

struct Bellman{
    int n,m;
    vector<node> e;           //边列表 
    vector<int> G[N];        //每个结点所连边的编号 
    bool in[N];         //在对列中的标记 
    int pre[N];         //转移边 
    int dis[N];         //最短路 
    int cnt[N];         //入队次数

    void init(int n)
    {
        this->n=n;
        e.clear();
        for (int i=1;i<=n;i++) G[i].clear();
    }

    void add(int u,int w,int z)
    {
        e.push_back((node){u,w,z});
        m=e.size();
        G[u].push_back(m-1);
    }

    bool fuhuan(int s)
    {
        queue<int> Q;
        memset(in,0,sizeof(in));
        memset(cnt,0,sizeof(cnt));
        for (int i=1;i<=n;i++)    //虚拟一个超级源点
        {
            dis[i]=0;
            in[i]=1;
            Q.push(i);
        }

        while (!Q.empty())
        {
            int now=Q.front(); Q.pop();
            in[now]=0;

            for (int i=0;i<G[now].size();i++)
            {
                node way=e[G[now][i]];
                int v=way.y;
                if (dis[v]>dis[now]+way.v)
                {
                    dis[v]=dis[now]+way.v;
                    pre[v]=G[now][i];
                    if (!in[v])
                    {
                        Q.push(v);
                        in[v]=1; 
                        if (++cnt[v]>n) return 1;
                    }
                }
            }
        }
        return 0;
    }
};

上面给出的朴素的Bellman,
如果我们只关心是否有负环(弱化最短路的求解)
我们可以使用dfs版本的Bellman(使用率不高)

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>

using namespace std;

const int N=200005;
const int mod=5000000;
struct node{
    int x,y,v,nxt;
};
node way[N<<1];
int st[N],tot=0;
int dis[N],n,m;
bool in[N],ff;

void add(int u,int w,int z)
{
    tot++;
    way[tot].x=u;way[tot].y=w;way[tot].v=z;way[tot].nxt=st[u];st[u]=tot;
}

void Bellman(int now)
{
    if (ff) return;                     //存在环 
    in[now]=1;
    for (int i=st[now];i;i=way[i].nxt)
        if (dis[way[i].y]>dis[now]+way[i].v&&ff==0)
        {
            dis[way[i].y]=dis[now]+way[i].v;
            if (in[way[i].y])
            {
                ff=1; return;
            } 
            else Bellman(way[i].y);
        }
    in[now]=0;                         //入栈状态 
    return;
}

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        memset(st,0,sizeof(st));
        tot=0;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++)
        {
            int u,w,z;
            scanf("%d%d%d",&u,&w,&z);
            add(u,w,z);
            if (z>=0) add(w,u,z);
        }
        memset(in,0,sizeof(in));             //访问记录 
        memset(dis,0,sizeof(dis));           //最短路 
        ff=0;
        for (int i=1;i<=n;i++)
        {
            Bellman(i);
            if (ff) break;
        }
        if (ff) printf("YE5\n");        //输出有毒 
        else printf("N0\n");
    }
    return 0;
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/wu_tongtong/article/details/78473018
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞