最短路判断是否出现负环。
SPFA过的,以前用Bellman。那是好久之前跟着一群大神混过去的,都忘了题了。
现在更深刻的理解图了。
给n点,m条正权边,w条负权边。
正权边是无向的,负权边是单向的。
判断是否出现了负环。
用SPFA,当某个点n 次入队了之后,肯定出现了负环。
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
#include<iostream>
#include<list>
#include<set>
#include<cmath>
#define INF 0x7fffffff
#define eps 1e-6
using namespace std;
int n,m,w;
struct lx
{
int v,t;
};
vector<lx>g[501];
bool SPFA(int start)
{
int path[501],dis[501];;
bool vis[501];
for(int i=1;i<=n;i++)
path[i]=vis[i]=0,dis[i]=INF;
queue<int>q;
dis[start]=0,vis[start]=1;
q.push(start);
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=0,path[u]++;
if(path[u]>n)return 1;
for(int j=0;j<g[u].size();j++)
{
int v=g[u][j].v;
int t=g[u][j].t;
if(dis[v]>dis[u]+t)
{
dis[v]=dis[u]+t;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&w);
for(int i=0;i<=n;i++)
g[i].clear();
int u,v,t;
lx now;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&t);
now.t=t;
now.v=v,g[u].push_back(now);
now.v=u,g[v].push_back(now);
}
bool start[501];
memset(start,0,sizeof(start));
while(w--)
{
scanf("%d%d%d",&u,&v,&t);
start[u]=v;
now.t=-t;//负权
now.v=v,g[u].push_back(now);
}
bool flag=0;
for(int i=1;i<=n;i++)
{
if(start[i])flag=SPFA(i);
if(flag)break;
}
if(flag)puts("YES");
else puts("NO");
}
}