spfa求负环

【模板】负环

题目描述

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

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

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

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

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

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

  • w0,则表示存在一条从 uv 边权为 w 的边,还存在一条从 vu 边权为 w 的边。
  • w<0,则只表示存在一条从 uv 边权为 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 @   Erfu  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示