POJ3259 Wormholes (Bellman-Ford最短路径算法)

本文出自:http://blog.csdn.net/svitter

原题:http://poj.org/problem?id=3259

题意:最基础的Bellman-Ford题目,寻找负环.告诉你有几个村庄,在村庄中有通路,通路走过去花费时间,通路是双向的,走虫洞可以使时间倒退,即负边.但是负边是单向的.

总结写在最前面:

Bellman-Ford算法最关键就在于判断有无负环;

Bellman-Ford算法刚刚自学,还不是很明白.一开始觉得使用邻接矩阵即可,想松弛n-1次以后看看还能不能再松弛,如果可以松弛说明有负环.一开始不过,心中甚是郁闷--(手懒不想写结构体..)实在无奈用了邻接表的形式(这才发现多写不了多少东西,输入的时候多加注意即可..)依然WA--这才好好看看了看..

问题在于:邻接表是对边处理,邻接矩阵则是对点处理.

在进行松弛操作的时候边的个数搞错了-=应该是m*2(双向边)+w(虫洞边)这才是最后的结果..也明白邻接表的速度要比邻接矩阵快的多..o(n^2)和O(n^3)明显不是一个级别--因此稀疏图还是要用邻接表.为了测试一下想法重写了邻接矩阵的算法,果然Time limit exception...不死心的我剪了剪枝还交了两次呵呵果然==再一次..

终于大彻大悟写了AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

#define INF 0x1f1f1f1f

int n, m ,w, e;
int res[505];
struct Edge
{
    int u;
    int v;
    int w;
};

Edge edge[6000];

bool bellman(int n, int m, int src)
{
    memset(res, 0x1f, sizeof(res));
    res[src] = 0;

    for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++)
    {
        e = res[edge[j].u] + edge[j].w;
        res[edge[j].v] = res[edge[j].v] <  e? res[edge[j].v] : e;
    }

    for(int i = 0; i < n; i++)
    for(int j = 0; j < m; j++)
    {
        if(res[edge[j].v] > res[edge[j].u] + edge[j].w)
            return 1;
    }
    return 0;
}

void ace()
{
    //work point;
    int i, j, k;
    //case
    int f;
    //num
    int s, e, c;

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

        //
        for(i = 0; i < m; i++)
        {
            scanf("%d%d%d", &s, &e, &c);
            //Two fields might be connected by more than one path.
            edge[i].u = s;
            edge[i].v = e;
            edge[i].w = c;
            edge[i + m].v = s;
            edge[i + m].u = e;
            edge[i + m].w = c;
        }

        //wormhole
        w += m * 2;
        for(i = m * 2; i < w; i++)
        {
            scanf("%d%d%d", &s, &e, &c);
            edge[i].u = s;
            edge[i].v = e;
            edge[i].w = -c;
        }
        m = w;//边数更改为w,包含虫洞,双向边.
        if(bellman(n, m, 1))
            printf("YES\n");
        else
            printf("NO\n");
    }
}

int main()
{
    ace();
    return 0;
}
时间: 2024-10-10 03:24:49

POJ3259 Wormholes (Bellman-Ford最短路径算法)的相关文章

Bellman ford 最短路径算法

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" /> 下表记录S到每一个节点的距离: 第一次迭代, S->A = 4 ,由于S->A眼下为INF.因此更新MIN(S->A)为4 S->B = 6.由于S->B眼下为INF.因此更新MIN(S->B)为6 S->C

18.boost Ford最短路径算法(效率低)

到某个节点最近距离                  最短路径当前节点的父节点 完整代码 1 #include <iostream> 2 #include <string> 3 #include <utility> 4 #include <vector> 5 #include <deque> 6 #include <boost/graph/adjacency_list.hpp> 7 //A*寻路算法 8 #include <bo

Bellman - Ford 算法解决最短路径问题

Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力不从心了,而Bellman - Ford算法可以解决这种问题. Bellman - Ford 算法可以处理路径权值为负数时的单源最短路径问题.设想可以从图中找到一个环路且这个环路中所有路径的权值之和为负.那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去.如果不处理这个负环路,程序就会永远运

Bellman—Ford算法思想

---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G运行Bellman—Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路.若存在负权回路,单源点最短路径问题无解:若不存在这样的回路,算法将给出从源点s到图G的任意顶点v的最短路径值d[v] Bellman—Ford算法流程 分为三个阶段: (1)初始化:将除源点外的所有顶点

ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可以求得一点到任意一点经过一条边的最短路,遍历两次可以求得一点到任意一点经过两条边的最短路...如 此反复,当遍历m次所有边后,则可以求得一点到任意一点经过m条边后的最短路(有点类似离散数学中邻接矩阵的连通性判定) POJ1556-The Doors 初学就先看POJ2240吧 题意:求从(0,5)到

Johnson 全源最短路径算法

解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: Bellman-Ford 单源最短路径算法:时间复杂度为 O(VE),适用于带负权值情况: 对于全源最短路径问题(All-Pairs Shortest Paths Problem),可以认为是单源最短路径问题的推广,即分别以每个顶点作为源顶点并求其至其它顶点的最短距离.例如,对每个顶点应用 Bel

Bellman-Ford 单源最短路径算法

Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Lester Ford 分别发表于 1958 年和 1956 年,而实际上 Edward F. Moore 也在 1957 年发布了相同的算法,因此,此算法也常被称为 Bellman-Ford-Moore 算法. Bellman-Ford 算法和 Dijkstra 算法同为解决单源最短路径的算法.对于带权有向

Floyd-Warshall 全源最短路径算法

Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Problem),其中图 G 允许存在权值为负的边,但不存在权值为负的回路.Floyd-Warshall 算法的运行时间为 Θ(V3). Floyd-Warshall 算法由 Robert Floyd 于 1962 年提出,但其实质上与 Bernad Roy 于 1959 年和 Stephen Warshal

POJ 3259 Wormholes Bellman题解

本题就是需要检查有没有负环存在于路径中,使用Bellman Ford算法可以检查是否有负环存在. 算法很简单,就是在Bellman Ford后面增加一个循环判断就可以了. 题目故事很奇怪,小心读题. #include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 501; const int MAX_M = 2501; const int MAX_W = 201; struct E