spfa求负环

【模板】负环

题目描述

给定一个 \(n\) 个点的有向图,请求出图中是否存在从顶点 \(1\) 出发能到达的负环。

负环的定义是:一条边权之和为负数的回路。

本题单测试点有多组测试数据

输入的第一行是一个整数 \(T\),表示测试数据的组数。对于每组数据的格式如下:

第一行有两个整数,分别表示图的点数 \(n\) 和接下来给出边信息的条数 \(m\)

接下来 \(m\) 行,每行三个整数 \(u, v, w\)

  • \(w \geq 0\),则表示存在一条从 \(u\)\(v\) 边权为 \(w\) 的边,还存在一条从 \(v\)\(u\) 边权为 \(w\) 的边。
  • \(w < 0\),则只表示存在一条从 \(u\)\(v\) 边权为 \(w\) 的边。

对于每组数据,输出一行一个字符串,若所求负环存在,则输出 YES,否则输出 NO

根据鸽巢定理每个点至多被入队\(n\)次,spfa判断入队次数不大于点数即可

核心代码:

                    if(++cnt[y] >= n)
                    {
                        puts("YES");
                        return;
                        
                    }

全部代码

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

const int N = 20005,M = 30003;

int h[N],w[M],e[M],ne[M],idx;
int n,m;
bool v[N];
int d[N],cnt[N];

queue<int>q;

void add(int x,int y,int z)
{
    e[++idx] = y,w[idx] = z;
    ne[idx] = h[x],h[x] = idx;
}

void spfa()
{
    
    memset(d,0x3f,sizeof d);
    memset(v,0,sizeof v);
    memset(cnt,0,sizeof cnt);
    d[1] = 0,v[1] = 1;
    cnt[1] = 0;
    q.push(1);
    while(q.size())
    {
        int x = q.front();q.pop();
        v[x] = 0;
        for(int i = h[x] ; i ;i = ne[i])
        {
            int y = e[i],z = w[i];
            if(d[y] > d[x] + z)
            {
                d[y] = d[x] + z;
                
                if(!v[y])
                {
                    
                    if(++cnt[y] >= n)
                    {
                        puts("YES");
                        return;
                        
                    }
                    
                    q.push(y),v[y] = 1;
                }
            }
        }
    }
    puts("NO");

}

int main()
{
    
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(h,0,sizeof h);
        memset(e,0,sizeof e);
        memset(ne,0,sizeof ne);
        memset(w,0,sizeof w);
        idx = 0; 
        scanf("%d%d",&n,&m);
        while(m--)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if(z < 0)
            add(x,y,z);
            else 
            {
                add(x,y,z);
                add(y,x,z);
            }
        }
        spfa();
    }



}
posted @ 2022-07-18 11:04  Erfu  阅读(55)  评论(0)    收藏  举报