[POJ 3259] Wormholes [SPFA]

来源:互联网 发布:网络歌曲女生唱的 编辑:程序博客网 时间:2024/05/17 01:56

Wormholes

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 54432 Accepted: 20270

Description

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 back T 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.

题意:

FJ有N块农场,农场间有M条路, W个虫洞。通过每条路需要耗费一定时间t,而通过每个虫洞则会增加一定时间 t’。问FJ能否从某个农场出发,最后回到这个点的时间在出发之前(即时间为负)。

题解:

理解清楚题意之后,我们将其当作图来考虑,每个农场为一个点,M条路是权值为正的双向边,W个虫洞是权值为负的单向边。于是我们只需要判断图中是否存在负圈即可。因为如果存在负圈,FJ只需要选择负圈种的某一点作为起点,即可回到过去的这个点。而如果不存在负圈,意味着FJ选择任何一个点作为起点都不可能从过去到达这个点。

比较裸的模板题,直接用spfa判断图中是否存在负圈即可。注意建图时,路是双向的,虫洞是单向的。

//#define LOCAL#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <vector>#include <map>#include <set>#include <stack>#include <queue>#include <iostream>#include <cstdlib>#include <algorithm>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 secondconst 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<edge> 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;}