While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..N, M (1 ≤ M≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.
As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .
To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.
Input
Line 1: A single integer, F. F farm descriptions follow.
Line 1 of each farm: Three space-separated integers respectively: N, M, and W
Lines 2.. M+1 of each farm: Three space-separated numbers ( S, E, T) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path.
Lines M+2.. M+ W+1 of each farm: Three space-separated numbers ( S, E, T) that describe, respectively: A one way path from S to E that also moves the traveler backT seconds.
Output
Lines 1.. F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).
Sample Input
2 3 3 1 1 2 2 1 3 4 2 3 1 3 1 3 3 2 1 1 2 3 2 3 4 3 1 8
Sample Output
NO YES
Hint
For farm 1, FJ cannot travel back in time.
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.
题解:本题要判负环。判负环可由Bellman-Ford(第n次仍更新,表明有负环存在),也可由SPFA(进队次数超过n次即存在负环)。
1:Bellman-Ford判负环
#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=10010;
struct Edge
{
int u,v,w;
} e[N];
int n,m,w,cnt;
int dis[N];
void add(int u,int v,int w)
{
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
cnt++;
}
int Bellman_Ford(int s)
{
memset(dis,INF,sizeof(dis));
dis[s]=0;
for(int i=1; i<=n-1; i++)
{
int flag=0;
for(int j=1; j<=cnt-1; j++)
{
if(dis[e[j].v]>dis[e[j].u]+e[j].w)
{
dis[e[j].v]=dis[e[j].u]+e[j].w;
flag=1;
}
}
if(flag==0)
return 0;
}
for(int j=1; j<=cnt-1; j++)
{
if(dis[e[j].v]>dis[e[j].u]+e[j].w)
return 1;
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cnt=1;
cin>>n>>m>>w;
for(int i=1; i<=m; i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
for(int i=1;i<=w;i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,-w);
}
int x=Bellman_Ford(1);
if(x==0)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}
2:SPFA判负环
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=10000;
const int INF=0x3f3f3f3f;
int head[maxn],dis[maxn],vis[maxn],num[maxn];
struct Edge
{
int v,w,next;
}e[maxn];
int n,m,w,cnt;
void add(int u,int v,int w)
{
e[cnt].v=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt++;
}
void Init()
{
cnt=1;
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
memset(head,-1,sizeof(head));
}
int SPFA(int s)
{
dis[s]=0;
queue<int>que;
que.push(s);
num[s]++;
while(!que.empty())
{
int u=que.front();
que.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
int w=e[i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(vis[v])
continue;
vis[v]=1;
num[v]++;
que.push(v);
if(num[v]>n)
return 1;
}
}
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
Init();
cin>>n>>m>>w;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
for(int i=1;i<=w;i++)
{
int u,v,w;
cin>>u>>v>>w;
add(u,v,-w);
}
int x=SPFA(1);
if(x==0)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}