Description
给定一个n个点m条边有向图,每条边有一个权值,试判断图中是否存在负环。
Input
第一行一个正整数T表示数据组数,对于每组数据
第一行两个正整数N M,表示图有N个顶点,M条边
接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)
Output
共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。
Solution
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define ll long long
#define N 2010
#define M 6010
using namespace std;
int cnt,head[N],vet[M],len[M],nxt[M],Vis[N];
int vis[N],dis[N],T,n,m,inque[N];
queue <int> Q;
inline ll read()
{
ll ans=0,f=1;
char ch=getchar();
while (ch<'0' || ch>'9')
{
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0' && ch<='9')
{
ans=ans*10+ch-'0';
ch=getchar();
}
return ans*f;
}
void init()
{
cnt=0;
memset(head,0,sizeof(head));
memset(vis,0,sizeof(vis));
memset(Vis,0,sizeof(Vis));
memset(inque,0,sizeof(inque));
memset(dis,0x7f7f7f7f,sizeof(dis));
}
void addedge(int u,int v,int l)
{
nxt[++cnt]=head[u];vet[cnt]=v;len[cnt]=l;head[u]=cnt;
}
bool SPFA(int u)
{
while (!Q.empty()) Q.pop();
Q.push(u);dis[u]=0;vis[u]=1;
while (!Q.empty())
{
int u=Q.front();
Q.pop();
Vis[u]=1;vis[u]=0;
for (int i=head[u];i;i=nxt[i])
{
int v=vet[i];
if (dis[u]+len[i]<dis[v])
{
dis[v]=dis[u]+len[i];
if (!vis[v])
{
vis[v]=1;
Q.push(v);
inque[v]++;
if (inque[v]>=n) return 1;
}
}
}
}
return 0;
}
int main()
{
T=read();
while (T--)
{
init();
n=read(),m=read();
for (int i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
if (w>=0) addedge(u,v,w),addedge(v,u,w);
else addedge(u,v,w);
}
bool flag=0;
for (int i=1;i<=n;i++)
{
if (Vis[i]) continue;
if (SPFA(i))
{
flag=1;
break;
}
}
if (!flag) printf("N0
"); else printf("YE5
");
}
return 0;
}