大概题意:农场里面有n个点m条边w个虫洞,m条边是双向边...a->b,b->a都是花费c分钟,虫洞的话是单向的,a点到b点时间会倒流c分钟就是-c分钟,然后问农场主是否能看到之前的自己...
大概也是个环?就是从起点出发在回到起点之后最短路更新最后从0能否变为负数...能负数就是能看到之前自己...大概是个负环吧...老老实实的去看spfa判断负环去了....
套了个模板...
发现了一个优化,因为这个题并不是一定要判断存在负环..所以可以再每次从队列中取出一个x进行松弛操作后判断一下dis[1]是否小于0,小于0就符合要求就是yes了...按照一个正常判断负环是906MS...判断小于0是235MS...差别还是蛮大的...
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define inf 200000000
int map[555][555],used[555];
int dis[555],n,num[555];
int spfa()
{
queue<int> q;
memset(used,0,sizeof(used));
memset(num,0,sizeof(num));
for(int i=1; i<=n; i++)
dis[i]=inf;
dis[1]=0;
q.push(1);
num[1]=1,used[1]=1;
while(!q.empty())
{
int x=q.front();
q.pop();
used[x]=0;
for(int i=1; i<=n; i++)
{
if(dis[i]>dis[x]+map[x][i])
{
dis[i]=dis[x]+map[x][i];
if(!used[i])
{
q.push(i);
used[i]=1;
num[i]++;
if(num[i]==n)
return 1;
}
}
}
if(dis[1]<0)//此处可以加一个优化...来判断是否提前符合了题意
return 1;
}
return 0;
}
int main()
{
int T,m,w;
cin>>T;
while(T--)
{
cin>>n>>m>>w;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
map[i][j]=inf;
}
for(int i=0; i<m; i++)
{
int u,v,s;
cin>>u>>v>>s;
map[u][v]=map[v][u]=min(s,map[u][v]);
}
for(int i=0; i<w; i++)
{
int u,v,s;
cin>>u>>v>>s;
map[u][v]=min(map[u][v],-s);
}
if(spfa())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}