spfa判断负环
题目链接
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;
}