POJ 3259 Wormholes (图论---最短路 Bellman-Ford || SPFA)
2014-05-27 11:33
639 查看
链接:http://poj.org/problem?id=3259
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
Sample Output
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.
题目大意:
有一个农场,里面有一些奇怪的单向虫洞,通过虫洞的入口到出口可以让时间倒退,农场主想知道他是否能够通过农场中的路和虫洞走回出发点,并且使时间倒退,给出农场中的N块地, M条路以及W个虫洞;
分析:
由题意可以看出实际目标位寻找负值回路,所以可以使用Bellman - Ford或者SPFA判断图中是否存在负权回路即可;
代码:
(Bellman - Ford):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 505
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;
typedef struct Edge_
{
int u, v, t;
}Edge;
Edge edge[6005];
int res[MAXN]; //存储源点到每个顶点的最短距离值;
int cas, n, m, w, s, e, t;
void READ_DATA()
{
scanf("%d %d %d", &n, &m, &w);
for(int i=0; i<m; i++) {
scanf("%d %d %d", &s, &e, &t);
edge[i].u = s, edge[i].v = e, edge[i].t = t;
edge[i+m].u = e, edge[i+m].v = s, edge[i+m].t = t;
}
for(int i=0; i<w; i++) {
scanf("%d %d %d", &s, &e, &t);
edge[i+2*m].u = s, edge[i+2*m].v = e, edge[i+2*m].t = -t;
}
}
bool Bellman(int n, int m, int src) //判断是否有负环;
{
memset(res, 0x1f, sizeof(res)); //初始化每个顶点的最短距离为无穷大;
res[src] = 0; //源点的距离为0;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(res[edge[j].u] + edge[j].t < res[edge[j].v]) res[edge[j].v] = res[edge[j].u] + edge[j].t;
}
}
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(res[edge[j].u] + edge[j].t < res[edge[j].v]) return true;
}
}
return false;
}
int main()
{
scanf("%d", &cas);
while(cas--) {
READ_DATA();
if(Bellman(n, 2*m+w, 1)) puts("YES");
else puts("NO");
}
return 0;
}
(SPFA):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 505
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;
int res[MAXN]; //存储源点到每个顶点的最短距离值;
int map[MAXN][MAXN];
int cnt[MAXN]; //每个点入队次数;
int que[MAXN*MAXN]; //队列;
bool In_que[MAXN]; //标记一个点是否出现在队列中;
int front, rear, cas; //队首,队尾,测试数据个数;
int n, m, w, s, e, t;
void READ_DATA()
{
scanf("%d %d %d", &n, &m, &w);
memset(map, 0x1f, sizeof(map));
for(int i=0; i<m; i++) {
scanf("%d %d %d", &s, &e, &t);
map[s][e] = map[e][s] = map[s][e] > t ? t : map[s][e];
}
for(int i=0; i<w; i++) {
scanf("%d %d %d", &s, &e, &t);
map[s][e] = map[s][e] < -t ? map[s][e] : -t;
}
}
bool SPFA(int n, int src)
{
RST(cnt), RST(In_que);
front = rear = 0;
que[++rear] = src;
cnt[src]++;
memset(res, 0x1f, sizeof(res));
res[src] = 0;
while(front < rear) {
int current = que[++front];
In_que[current] = 0;
for(int i=1; i<=n; i++) {
if(res[current] + map[current][i] < res[i]) {
res[i] = res[current] + map[current][i];
if(!In_que[i]) {
que[++rear] = i, cnt[i]++;
if(cnt[i] >= n) return true;
}
}
}
}
return false;
}
int main()
{
scanf("%d", &cas);
while(cas--) {
READ_DATA();
if(SPFA(n, 1)) puts("YES");
else puts("NO");
}
return 0;
}
转载请注明出处:blog.csdn.net/keshacookie
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.
题目大意:
有一个农场,里面有一些奇怪的单向虫洞,通过虫洞的入口到出口可以让时间倒退,农场主想知道他是否能够通过农场中的路和虫洞走回出发点,并且使时间倒退,给出农场中的N块地, M条路以及W个虫洞;
分析:
由题意可以看出实际目标位寻找负值回路,所以可以使用Bellman - Ford或者SPFA判断图中是否存在负权回路即可;
代码:
(Bellman - Ford):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 505
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;
typedef struct Edge_
{
int u, v, t;
}Edge;
Edge edge[6005];
int res[MAXN]; //存储源点到每个顶点的最短距离值;
int cas, n, m, w, s, e, t;
void READ_DATA()
{
scanf("%d %d %d", &n, &m, &w);
for(int i=0; i<m; i++) {
scanf("%d %d %d", &s, &e, &t);
edge[i].u = s, edge[i].v = e, edge[i].t = t;
edge[i+m].u = e, edge[i+m].v = s, edge[i+m].t = t;
}
for(int i=0; i<w; i++) {
scanf("%d %d %d", &s, &e, &t);
edge[i+2*m].u = s, edge[i+2*m].v = e, edge[i+2*m].t = -t;
}
}
bool Bellman(int n, int m, int src) //判断是否有负环;
{
memset(res, 0x1f, sizeof(res)); //初始化每个顶点的最短距离为无穷大;
res[src] = 0; //源点的距离为0;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(res[edge[j].u] + edge[j].t < res[edge[j].v]) res[edge[j].v] = res[edge[j].u] + edge[j].t;
}
}
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
if(res[edge[j].u] + edge[j].t < res[edge[j].v]) return true;
}
}
return false;
}
int main()
{
scanf("%d", &cas);
while(cas--) {
READ_DATA();
if(Bellman(n, 2*m+w, 1)) puts("YES");
else puts("NO");
}
return 0;
}
(SPFA):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 505
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;
int res[MAXN]; //存储源点到每个顶点的最短距离值;
int map[MAXN][MAXN];
int cnt[MAXN]; //每个点入队次数;
int que[MAXN*MAXN]; //队列;
bool In_que[MAXN]; //标记一个点是否出现在队列中;
int front, rear, cas; //队首,队尾,测试数据个数;
int n, m, w, s, e, t;
void READ_DATA()
{
scanf("%d %d %d", &n, &m, &w);
memset(map, 0x1f, sizeof(map));
for(int i=0; i<m; i++) {
scanf("%d %d %d", &s, &e, &t);
map[s][e] = map[e][s] = map[s][e] > t ? t : map[s][e];
}
for(int i=0; i<w; i++) {
scanf("%d %d %d", &s, &e, &t);
map[s][e] = map[s][e] < -t ? map[s][e] : -t;
}
}
bool SPFA(int n, int src)
{
RST(cnt), RST(In_que);
front = rear = 0;
que[++rear] = src;
cnt[src]++;
memset(res, 0x1f, sizeof(res));
res[src] = 0;
while(front < rear) {
int current = que[++front];
In_que[current] = 0;
for(int i=1; i<=n; i++) {
if(res[current] + map[current][i] < res[i]) {
res[i] = res[current] + map[current][i];
if(!In_que[i]) {
que[++rear] = i, cnt[i]++;
if(cnt[i] >= n) return true;
}
}
}
}
return false;
}
int main()
{
scanf("%d", &cas);
while(cas--) {
READ_DATA();
if(SPFA(n, 1)) puts("YES");
else puts("NO");
}
return 0;
}
转载请注明出处:blog.csdn.net/keshacookie
相关文章推荐
- Wormholes( POJ 3259)(Bellman-Ford+SPFA)(判断是否有负权环)(最短路模板)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- (POJ 3259)Wormholes 判断负环 bellman_ford 或者 spfa
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes(判断负权回路|SPFA||Bellman-Ford)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)
- POJ 3259 Wormholes(最短路Bellman_Ford)
- poj 3259 Wormholes(SPFA || Bellman-Ford)
- POJ 3259-Wormholes (Bellman-Ford&&SPFA) (模板题)
- POJ 3259 Wormholes (判断负环,SPFA或Bellman-Ford都可)
- POJ 3259 Wormholes (Bellman-ford或SPFA)
- POJ训练计划3259_Wormholes(Bellman-Ford)(SPFA)
- 最短路(Bellman_Ford) POJ 3259 Wormholes
- POJ 3259 Wormholes 图论 贝尔曼-福特算法(Bellman-Ford)
- POJ 3259 Wormholes(判断负环&(Bellman-Ford|SPFA))
- Bellman-Ford||SPFA-POJ-3259-Wormholes
- 【POJ 3259】Wormholes(最短路SPFA/Bellman_Ford)
- POJ 3259 Wormholes (Bellman-Ford/SPFA 判断是否存在负权环)