「POJ3259」Wormholes - SPFA判负环
Posted horrigue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「POJ3259」Wormholes - SPFA判负环相关的知识,希望对你有一定的参考价值。
Wormholes
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 65211 Accepted: 24284
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.
农夫约翰在探索他的许多农场,发现了一些惊人的虫洞。虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的前达到目的地!他的 (N(1≤N≤500)) 个农场被编号为 (1)..(N),之间有 (M(1≤M≤2500)) 条路径,(W(1≤W≤200)) 个虫洞。作为一个狂热的时间旅行 (FJ) 的爱好者,他要做到以下几点:开始在一个区域,通过一些路径和虫洞旅行,他要回到最开时出发的那个区域出发前的时间。也许他就能遇到自己了:)。为了帮助 (FJ) 找出这是否是可以或不可以,他会为你提供 (F) 个农场的完整的映射到 ((1≤F≤5)) 。所有的路径所花时间都不大于 (10000) 秒,所有的虫洞都不大于万秒的时间回溯。
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.
第 (1) 行:一个整数 (F) 表示接下来会有 (F) 个农场说明。
每个农场第一行:分别是三个空格隔开的整数: (N),(M) 和 (W)
第 (2) 行到 (M+1) 行:三个空格分开的数字 ((S,E,T)) 描述,分别为:需要 (T) 秒走过 (S) 和 (E) 之间的双向路径。两个区域可能由一个以上的路径来连接。
第 (M +2) 到 (M+ W+1) 行:三个空格分开的数字 ((S,E,T)) 描述虫洞,描述单向路径, (S) 到 (E) 且回溯 (T) 秒。
Output
Lines 1..F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).
(F) 行,每行代表一个农场
每个农场单独的一行, “(YES)”表示能满足要求,”(NO)”表示不能满足要求。
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.
思路
想要回到原点,虫洞让你回到过去(饥荒玩家表示b这并不能),相当于一个负权,然后判断f是否存在负环即可。
代码
#include<cstdio>
#include<cctype>
#include<iostream>
#include<queue>
#include<cstring>
#define rg register
#define int long long
using namespace std;
inline int read(){
rg int f = 0, x = 0;
rg char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while( isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return f? -x: x;
}
const int N = 6010;
const int inf = 0x7f7f7f7f;
int T, n, m, k, head[N], tot, dis[N], u, v, w, cnt[N];
bool vis[N];
struct edge{
int nxt, to, w;
}e[N << 1];
inline void init(){
for(rg int i = 1; i <= n; ++i){
if(vis[i]) vis[i] = 0;
if(head[i]) head[i] = 0;
if(cnt[i]) cnt[i] = 0;
}
memset(e, 0, sizeof(e));
tot = 0;
}
inline void add(rg int u, rg int v, rg int w){
e[++tot].nxt = head[u];
e[tot].to = v;
e[tot].w = w;
head[u] = tot;
}
inline bool spfa(){
for(rg int i = 1; i <= n; ++i) dis[i] = inf;
queue<int > q;
dis[1] = 0;
vis[1] = 1;
q.push(1);
while(!q.empty()){
int u = q.front();
vis[u] = false;
q.pop();
for(rg int i = head[u]; i; i = e[i].nxt){
int v = e[i].to;
if(dis[v] > dis[u] + e[i].w){
dis[v] = dis[u] + e[i].w;
cnt[v] = cnt[u] + 1;
if(cnt[v] >= n) return true; //注意是 >= n
if(!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
return false;
}
signed main(){
T = read();
for(rg int o = 1; o <= T; ++o){
n = read(), m = read(), k = read();
if(o > 1) init();
for(rg int i = 1; i <= m; ++i){
u = read(), v = read(), w = read();
add(u, v, w);
add(v, u, w);
}
for(rg int i = 1; i <= k; ++i){
u = read(), v = read(), w = read();
add(u, v, -w);
}
if(spfa()) puts("YES");
else puts("NO");
}
return 0;
}
以上是关于「POJ3259」Wormholes - SPFA判负环的主要内容,如果未能解决你的问题,请参考以下文章