POJ3259 HYSBZ1715(BZOJ1715) Wormholes【Bellman ford算法】

Wormholes

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 60687 Accepted: 22655

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.

Source

USACO 2006 December Gold

问题链接POJ3259 HYSBZ1715(BZOJ1715) Wormholes

问题描述:(略)

问题分析

  这个问题采用Bellman ford算法来解。

  解法一采用邻接矩阵存储图,顶点数为n,其算法复杂度为O(n^3)。

  解法二采用邻接表存储图,顶点数为n,边数为e,其算法复杂度为O(n*e)。

程序说明

  采用解法一时,使用函数min(),程序会超时,有点奇怪。代码写法是:

  grid[i][j] = min(grid[i][j], grid[i][k] + grid[k][j]); 

参考链接:(略)


AC的C++语言程序(解法二)如下:

/* POJ3259 HYSBZ1715(BZOJ1715) Wormholes */

#include <iostream>
#include <stdio.h>

using namespace std;

const int INF = 1 << 30;
const int N = 500;
const int M = 2500;
const int W = 200;
int n, m, w, cnt;
int dist[N + 1];

struct Edge {
    int src, dest, cost;
} edges[M * 2 + W];

bool bellman_ford(int v) {
    for( int i = 1; i <= n; i++)
        dist[i] = INF;

    dist[v] = 0;
    for( int k = 1; k < n; k++) {       // 经过不超过k条边
        for( int i = 0; i < cnt; i++) {
            int s = edges[i].src;
            int e = edges[i].dest;
            if( dist[s] + edges[i].cost < dist[e])
                dist[e] = dist[s] + edges[i].cost;
        }
    }

    for( int i = 0; i < cnt; i++) {
        int s = edges[i].src;
        int e = edges[i].dest;
        if( dist[s] + edges[i].cost < dist[e])
            return true;
    }

    return false;
}

int main()
{
    int f;
    scanf("%d", &f);
    while(f--) {
        scanf("%d%d%d", &n, &m, &w);

        int s, e, t;
        cnt = 0;
        for(int i = 0; i < m; i++) {
            scanf("%d%d%d", &s, &e, &t);
            edges[cnt].src = s;
            edges[cnt].dest = e;
            edges[cnt++].cost = t;
            edges[cnt].src = e;
            edges[cnt].dest = s;
            edges[cnt++].cost = t;
        }

        for(int i = 0; i < w; i++) {
            scanf("%d%d%d", &s, &e, &t);
            edges[cnt].src = s;
            edges[cnt].dest = e;
            edges[cnt++].cost = -t;
        }

        // 输出结果
        printf("%s\n", bellman_ford(1) ? "YES" : "NO");
    }

    return 0;
}


AC的C++语言程序(解法一)如下:

/* POJ3259 HYSBZ1715(BZOJ1715) Wormholes */

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

const int INF = 0x3f;
const int N = 500;
int n, m, k, grid[N + 1][N + 1];

bool bellman_floyd()
{
    for(int k = 1; k <= n; k++)
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <=n; j++) {
                int t = grid[i][k] + grid[k][j];
                if(grid[i][j] > t)
                    grid[i][j] = t;
            }
            if(grid[i][i] < 0)
                return true;
    }
    return false;
}

int main()
{
    int f;
    scanf("%d", &f);
    while(f--) {
        scanf("%d%d%d", &n, &m, &k);

        memset(grid, INF, sizeof(grid));
        for(int i = 1; i <= n; i++)
            grid[i][i] = 0;

        int a, b, c;
        for(int i = 1; i <= m; i++) {
            scanf("%d%d%d", &a, &b, &c);
            if(c < grid[a][b])
                grid[a][b] = grid[b][a] = c;
        }

        for(int i = 1; i <= k; i++) {
            scanf("%d%d%d", &a, &b, &c);
            grid[a][b] = -c;
        }

        // 输出结果
        printf("%s\n", bellman_floyd() ? "YES" : "NO");
    }

    return 0;
}

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/tigerisland45/article/details/80781990
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞