Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 54432 Accepted: 20270
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.
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 back T seconds.
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
NO
YES
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.
FJ有N块农场,农场间有M条路, W个虫洞。通过每条路需要耗费一定时间t,而通过每个虫洞则会增加一定时间 t’。问FJ能否从某个农场出发,最后回到这个点的时间在出发之前(即时间为负)。
理解清楚题意之后,我们将其当作图来考虑,每个农场为一个点,M条路是权值为正的双向边,W个虫洞是权值为负的单向边。于是我们只需要判断图中是否存在负圈即可。因为如果存在负圈,FJ只需要选择负圈种的某一点作为起点,即可回到过去的这个点。而如果不存在负圈,意味着FJ选择任何一个点作为起点都不可能从过去到达这个点。
比较裸的模板题,直接用spfa判断图中是否存在负圈即可。注意建图时,路是双向的,虫洞是单向的。
//#define LOCAL
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define LL long long
#define ll long long
#define INF 0x3f3f3f3f
#define maxn MAX_N
#define MOD mod
#define MMT(x,i) memset(x,i,sizeof(x))
#define REP(i, n) for(int i = 0; i < n; i++)
#define FOR(i, n) for(int i = 1; i <= n; i++)
#define pb push_back
#define mp make_pair
#define X first
#define Y second
const LL MOD = 1e9 + 7;
const double pi = acos(-1.0);
const double E = exp(1);
const double EPS = 1e-8;
const int MAX_N = 1000010;
const int MAX_V = 510;
int N, M, W;
int dis[MAX_V];
int cnt[MAX_V];
bool vis[MAX_V];
struct edge{
int to, cost;
edge(int a, int b): to(a), cost(b){}
};
vector G[MAX_V];
void addedge(int u, int v, int w)
{
G[u].push_back(edge(v, w));
// G[v].push_back(edge(u, w));
}
bool spfa_bfs(int s)
{
MMT(dis, 0x3f);
MMT(cnt, 0);
MMT(vis, 0);
queue<int> q;
dis[s] = 0, cnt[s] = 1, vis[s] = 1;
q.push(s);
while(!q.empty())
{
int x = q.front();
q.pop();
vis[x] = 0;
for(int i = 0; i< G[x].size(); i++)
{
int v = G[x][i].to, cost = G[x][i].cost;
if(dis[v] > dis[x] + cost)
{
dis[v] = dis[x] + cost;
// cout << v << " " << dis[v] << endl;
//if(dis[v] < 0) return 0;
if(!vis[v]){
vis[v] = 1;
cnt[v]++;
q.push(v);
if(cnt[v] > N) return 0;
}
}
}
}
return 1;
}
void init()
{
for(int i = 0; i < MAX_V; i++)
G[i].clear();
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
int T;
int u, v, w;
cin >> T;
while(T--)
{
cin >> N >> M >> W;
init();
REP(i, M)
{
cin >> u >> v >> w;
addedge(u, v, w);
addedge(v, u, w);
}
REP(i, W)
{
cin >> u >> v >> w;
addedge(u, v, -w);
}
bool flag = 1;
if(!spfa_bfs(1)){
cout << "YES" << endl;
flag = 0;
}
if(flag) cout << "NO" << endl;
}
return 0;
}