spfa判断负环

题目链接

acwing852. spfa判断负环

P3385 【模板】负环


acwing852. spfa判断负环

题目描述

给定一个 \(n\) 个点 \(m\) 条边的有向图,图中可能存在重边和自环, 边权可能为负数。

请你判断图中是否存在负权回路。

输入格式

第一行包含整数 \(n\)\(m\)

接下来 \(m\) 行每行包含三个整数 \(x,y,z\),表示存在一条从点 \(x\) 到点 \(y\) 的有向边,边长为 \(z\)

输出格式

如果图中存在负权回路,则输出 Yes,否则输出 No

数据范围

\(1≤n≤2000\),
\(1≤m≤10000\),
图中涉及边长绝对值均不超过 \(10000\)

输入样例:

3 3
1 2 -1
2 3 4
3 1 -4

输出样例:

Yes
  • 时间复杂度:\(O(kn)\)
#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int n,m;
int cnt[N];
int d[N];
bool v[N];
vector<pair<int,int>> adj[N];
bool spfa()
{
    queue<int> q;
    for(int i=1;i<=n;i++)
    {
        q.push(i);
        v[i]=true;
    }
    while(q.size())
    {
        int x=q.front();
        q.pop();
        v[x]=false;
        for(auto [y,w]:adj[x])
        {
            if(d[y]>d[x]+w)
            {
                d[y]=d[x]+w;
                cnt[y]=cnt[x]+1;
                if(cnt[y]>=n)return true;
                v[y]=true;
                q.push(y);
            }
        }
    }
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        adj[x].emplace_back(y,z);
    }
    puts(spfa()?"Yes":"No");
    return 0;
}

P3385 【模板】负环

题目描述

给定一个 \(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。

输入

2
3 4
1 2 2
1 3 4
2 3 1
3 1 -3
3 3
1 2 3
2 3 4
3 1 -8

输出

NO
YES

说明/提示

数据规模与约定
对于全部的测试点,保证:

\(1 \leq n \leq 2 \times 10^3 ,1 \leq m \leq 3 \times 10^3\)
\(1 \leq u, v \leq n,-10^4 \leq w \leq 10^4\)
\(1 \leq T \leq 10\)

提示

请注意,\(m\) 不是图的边数。
注意:本题 \(d\) 数组需要初始化

  • 时间复杂度:\(O(kn)\)

代码

#include<bits/stdc++.h>
using namespace std;
const int N=2010;
int n,m;
int cnt[N];
int d[N];
bool v[N];
vector<pair<int,int>> adj[N];
bool spfa()
{
    memset(v,0,sizeof v);
    memset(d,0x3f,sizeof d);
    memset(cnt,0,sizeof cnt);
    queue<int> q;
    q.push(1);
    v[1]=true;
    d[1]=0;
    while(q.size())
    {
        int x=q.front();
        q.pop();
        v[x]=false;
        for(auto [y,w]:adj[x])
        {
            if(d[y]>d[x]+w)
            {
                d[y]=d[x]+w;
                cnt[y]=cnt[x]+1;
                if(cnt[y]>=n)return true;
                if(!v[y])
                {
                    v[y]=true;
                    q.push(y);
                }

            }
        }
    }
    return false;
}
int main()
{
    int t;
    for(scanf("%d",&t);t;t--)
    {
        scanf("%d%d",&n,&m);
        memset(adj,0,sizeof adj);
        while(m--)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            adj[x].emplace_back(y,z);
            if(z>=0)
                adj[y].emplace_back(x,z);

        }
        puts(spfa()?"YES":"NO");
    }
    return 0;
}

posted @ 2021-09-23 17:12  zyy2001  阅读(116)  评论(0编辑  收藏  举报