spfa判负环

模板题

题目描述

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

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

输入格式

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

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

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

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

  • w0,则表示存在一条从 uv 边权为 w 的边,还存在一条从 vu 边权为 w 的边。
  • w<0,则只表示存在一条从 uv 边权为 w 的边。

输出格式

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

样例 #1

样例输入 #1

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

样例输出 #1

NO
YES

提示

数据规模与约定

对于全部的测试点,保证:

  • 1n2×1031m3×103
  • 1u,vn104w104
  • 1T10

提示

请注意,m 不是图的边数。

code

#include <bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10;
int n, m;
vector<pair<int, int> > e[N];
int d[N], cnt[N];//cnt[x]表示1-x的最短路包含的边数
bool vis[N];
bool spfa() {
queue<int> q;
memset(d, 0x3f, sizeof d);
memset(vis, 0, sizeof vis);
memset(cnt, 0, sizeof cnt);
d[1] = 0, vis[1] = 1;
q.push(1);
while (!q.empty()) {
int x = q.front(); q.pop();
vis[x] = 0;
for (int i = 0; i < e[x].size(); i ++) {
int y = e[x][i].first, z = e[x][i].second;
if (d[y] > d[x] + z) {
d[y] = d[x] + z;
cnt[y] = cnt[x] + 1;//记录最短路径的边数
if (cnt[y] >= n) return 1;
//最多n-1条边就包含n个点,边数大等于n,说明有负环
if (!vis[y]) {
q.push(y);
vis[y] = 1;
}
}
}
}
return 0;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T; cin >> T;
while (T --) {
for (int i = 1; i <= N; i ++) e[i].clear();
cin >> n >> m;
for (int i = 1; i <= m; i ++) {
int u, v, w; cin >> u >> v >> w;
e[u].push_back(make_pair(v, w));
if (w >= 0) e[v].push_back(make_pair(u, w));
}
puts(spfa() ? "YES" : "NO");
}
return 0;
}

image



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   YHXo  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示