n个点,有m条正权双向边,w条负权单向边,判断是否存在负环
spfa,可以先将所有点加入队列或者对多个点SPFA避免不联通的情况
不过数据有点弱,不判也可过
//判断是否存在负环,数据有点弱,如果从1和负环不联通应该是不能通过的,可以改成多次spfa,每次从没经过的点开始spfa
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cmath>
using namespace std;
typedef pair<int,int> PII;
const int MAXN=507;
const int MAXM=MAXN*MAXN/2;
const int INF=0x3f3f3f3f;
int head[MAXN],to[MAXM<<1],ne[MAXM<<1],n,m,w,ecnt,T;
int dist[MAXN],wt[MAXM<<1];
void init()
{
ecnt=0;
memset(head,0,sizeof(head));
}
void addedge(int a,int b,int c)
{
ne[++ecnt]=head[a];
head[a]=ecnt;
to[ecnt]=b;
wt[ecnt]=c;
}
queue<int> q;
int inq[MAXN],vis[MAXN];
bool spfa(int s)
{
while(!q.empty())
q.pop();
for(int i=1;i<=n;i++)
dist[i]=INF,inq[i]=0,vis[i]=0;
dist[s]=0;
inq[s]=1;
q.push(s);
int ta;
while(!q.empty())
{
int fr=q.front();
q.pop();
inq[fr]=0;
for(int i=head[fr];i;i=ne[i])
{
int v=to[i];
ta=dist[fr]+wt[i];
if(dist[v]>ta)
{
if(v==s)//若给起点更新
return true;
dist[v]=ta;
if(inq[v])continue;
if(++vis[v]>=n)//存在负环
return true;
inq[v]=1;
q.push(v);
}
}
}
return false;
}
int main()
{
int st,ta,tb,tc,td;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&td);
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&ta,&tb,&tc);
addedge(ta,tb,tc);
addedge(tb,ta,tc);
}
for(int i=1;i<=td;i++)
{
scanf("%d%d%d",&ta,&tb,&tc);
addedge(ta,tb,-tc);
}
printf("%s\n",spfa(1)?"YES":"NO");
}
return 0;
}