POJ 3259 -- 最短路径 ( bellman ford算法, 允许负权边)

图论 最短路径 bellman ford算法

题意

N个点的图,2M条正权双向边,W条负权单向边。问图中是否存在负环?

题解

用bellman-ford算法判断。

  • bellman-ford算法在挑战程序设计竞赛中的P100

代码

#include <iostream>
using namespace std;
const int MAXN = 10000;
const int INF = (1<<26);
int dis[MAXN];
int F;
int N, M, W;
int m;
struct Edge{ int from, to, cost; } edge[MAXN];

int result;
bool bellman_ford()
{
    for(int i = 0; i <= N; i++)
        dis[i] = INF;
    dis[1] = 0;
    bool update;
    for(int i = 0; i < N - 1; i++) //之所以是n-1次: 考虑一个最长的最短路径有n-1条边,若边的顺序是逆向的存储的,则一次只用了一条边来更新,一共需要n-1 次
    {
        update = false;
        for(int j = 0; j < m; j++)
        {
            Edge e = edge[j];
            if(dis[e.from] < INF && dis[e.from] + e.cost < dis[e.to])
            {
                dis[e.to] = dis[e.from] + e.cost;
                update = true;
            }
        }
        if(!update)
            break;

    }
    for(int j = 0; j < m; j++) //若第n次还在更新最短路径,则有负权边
    {
        Edge e = edge[j];
        if(dis[e.from] + e.cost < dis[e.to])
            return false;
    }
    return true;
}
bool solve()
{
    return !bellman_ford();
}


int main()
{
    cin >> F;
    while(F--)
    {

        cin >> N >> M >> W;
        int s, e, t;
        m = 0;
        for(int i = 0; i < M; i++) // bidirectional path
        {
            cin >> s >> e >> t;
            edge[m].from = s , edge[m].to = e , edge[m++].cost = t;
            edge[m].from = e , edge[m].to = s , edge[m++].cost = t;
        }

        for(int i = 0; i < W; i++)
        {
            cin >> s >> e >> t;
            edge[m].from = s , edge[m].to = e , edge[m++].cost = -t;

        }

        if(!bellman_ford())
            cout << "YES" << endl;
        else
            cout << "NO" << endl;

    }


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