能过洛谷的数据,但一些别的数据就过不了
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int head[2010], edge_number, dis[2010], cnt[2010], n, m;//cnt用于记录每个点的最短路径的边数,令cnt[1]=1,则对于任意一点point,cnt[point]>m时说明有负环
bool inq[2010];//点是否在队列中
//下面的是链式前向星
struct Edge
{
int nxt, v, w;
}edge[6010];
inline void add_edge(int u, int v, int w)
{
edge[++edge_number].nxt = head[u];
edge[edge_number].v = v;
edge[edge_number].w = w;
head[u] = edge_number;
}
//上面的是链式前向星
inline void spfa()
{
queue<int>q;//每次建一个队列
q.push(1); inq[1] = true;//压入初始点1
while (!q.empty())
{
int u = q.front(); q.pop(); inq[u] = false;//取出队头
for (int j = head[u]; j; j = edge[j].nxt)//循环遍历每一个队头指向的点
{
int& v = edge[j].v;//方便一点,用v表示当前遍历到的边的终点
if (cnt[v] > m)//如果边数超过m了那就结束函数
{
printf("YES\n");
return;
}
if (dis[v] > dis[u] + edge[j].w)
{
if (!inq[v])
{
q.push(v); inq[v] = true;
}
dis[v] = dis[u] + edge[j].w;
cnt[v] = cnt[u] + 1;//更新了距离之后也更新边数
}
if (cnt[v] > m)//如果边数超过m了那就结束函数
{
printf("YES\n");
return;
}
}
}//程序能走到这里说明没有负环 输出
printf("NO\n"); return;
}
int main()
{
int t; scanf("%d", &t);
for (; t; t--)
{//下面是各种清零
memset(head, 0, sizeof(head));
memset(dis, 0x3f3f3f3f, sizeof(dis));
memset(inq, 0, sizeof(inq));
memset(cnt, 0, sizeof(cnt));
memset(edge, 0, sizeof(edge));
dis[1] = 0; cnt[1] = 0; edge_number = 0;//初始化
scanf("%d%d", &n, &m);
for (int h = 0; h < m; h++)
{
int u, v, w; scanf("%d%d%d", &u, &v, &w);
if (w >= 0)
{//正边权就一来一回
add_edge(u, v, w);
add_edge(v, u, w);
}
else
{//负边权就有去无回
add_edge(u, v, w);
}
}
spfa();
}
return 0;