>Link
ybtoj判断负环
>解题思路
特别坑的一道题,搞得我检查了好久(所以要认真审题TT)
坑1:输出的“YE5”,“N0”,后面那两个实际上是数字
坑2:当边权不为负数时是无向边,边权为负数时是有向边
我们从1开始跑一个最短路spfa,如果存在负环的话我们就会在这个环上一直跑下去
所以记录下每条路径经过的边数,经过的边多于总数
m
m
m的话,就说明存在负环
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 3010
using namespace std;
queue<int> Q;
struct edge
{
int to, next, w;
} e[2 * N];
int T, n, m, cnt, h[N], c[N], sum[N];
bool mark[N];
void work ()
{
memset (c, 0x7f, sizeof (c));
memset (mark, 0, sizeof (mark));
memset (sum, 0, sizeof (sum));
memset (h, 0, sizeof (h));
cnt = 0;
int u, v, w;
scanf ("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
{
scanf ("%d%d%d", &u, &v, &w);
e[++cnt] = (edge){v, h[u], w};
h[u] = cnt;
if (w >= 0)
{
e[++cnt] = (edge){u, h[v], w};
h[v] = cnt;
}
}
c[1] = 0, mark[1] = 1;
Q.push(1);
while (!Q.empty())
{
int u = Q.front();
Q.pop();
mark[u] = 0;
for (int i = h[u]; i; i = e[i].next)
{
int v = e[i].to;
if (c[v] > c[u] + e[i].w)
{
c[v] = c[u] + e[i].w;
sum[v] = sum[u] + 1;
if (!mark[v])
{
mark[v] = 1;
Q.push(v);
}
if (sum[v] > m)
{
printf ("YE5\n");
return;
}
}
}
}
printf ("N0\n");
}
int main()
{
scanf ("%d", &T);
while (T--) work ();
return 0;
}