spfa求负环
【模板】负环
题目描述
给定一个 个点的有向图,请求出图中是否存在从顶点 出发能到达的负环。
负环的定义是:一条边权之和为负数的回路。
本题单测试点有多组测试数据。
输入的第一行是一个整数 ,表示测试数据的组数。对于每组数据的格式如下:
第一行有两个整数,分别表示图的点数 和接下来给出边信息的条数 。
接下来 行,每行三个整数 。
- 若 ,则表示存在一条从 至 边权为 的边,还存在一条从 至 边权为 的边。
- 若 ,则只表示存在一条从 至 边权为 的边。
对于每组数据,输出一行一个字符串,若所求负环存在,则输出 YES
,否则输出 NO
。
根据鸽巢定理每个点至多被入队次,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();
}
}
“风雪越是呼啸,雪莲越是绽放”
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理