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;
}


你可能感兴趣的:(C++,ACM,图论)