Poj 1860 && poj 3259 剖析bellman_ford算法

剖析bellman_ford算法

花费了1天半的时间终于把bellman_ford算法搞透彻,百度了许多大牛的博客但是其中有一点依然不明白,不过今天终于明白了,写一篇博客好好剖析剖析!!!

首先介绍一个概念:松弛每次松弛操作实际上是对相邻节点的访问,第《Poj 1860 && poj 3259 剖析bellman_ford算法》次松弛操作保证了所有深度为n的路径最短。由于图的最短路径最长不会经过超过《Poj 1860 && poj 3259 剖析bellman_ford算法》条边,所以可知贝尔曼-福特算法所得为最短路径。

算法能解决的问题判断最短路中是否有正环或负环。


算法具体流程


1、循环n-1次。
2、对于每一次循环松弛边
3,最后判断一下松弛完的边是否还能松弛
算法证明


流程 1


为什么要循环n-1次呢?
搜了好多博客,都没给讲明白,下面是我自己的理解,有错误之处欢迎大牛指教一二。
首先我们假设要有这样的常识,如果最短路存在,那么对于最短路中一定是无环的,如果有环的话那么我们可以一直沿着环走,那么我们得到的路一定不是最短路,所以对于n个点最多有n-1条边构成最短路,如果我们要得到的是最短路,那么我们就把除了原点以外的点初始化为无穷大(为了松弛),那么我们第一次松弛就得到了第一层的路,而除了原点以外的边并没有被松弛,想一想为什么?,如果是最长路那么就出使是的,我们第二次松弛的时候就把第一次松弛的点再往外扩
展一层,这是在他们的基础上在得到一层,说到这里大家就该明白为什么要循环n-1次。
流程 2


d[v] = max(d[v],d[u]+w);


流程 3


对于所有的点我们都已经松弛过,如果还能还能在松弛说明存在负权边。
poj1860 && poj 3259 是同样的题目没什么好说的。只介绍一下3259这道题。
n块地,m条边,w个虫洞
虫洞可以时间倒流,问你是否能回到从前。


思路


对于虫洞加负权有向边,然后判断负环


#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
int n,m,w,n1,m1,w1;
struct Node
{
    int u,v,w;
}a[10000];
int cur = 0;
bool bellman()
{
    int d[10000];
    memset(d,63,sizeof(d));
    d[1] = 0;

    for(int i=1;i<n;i++)
    {
        bool finsh = false;
        for(int j=0;j<cur;j++)
        {
            if(d[a[j].v]>d[a[j].u]+a[j].w){
                d[a[j].v] = d[a[j].u] + a[j].w;
                finsh = true;
            }
        }
        if(!finsh)break;
    }
    for(int j=0;j<cur;j++)
    {
        if(d[a[j].v]>d[a[j].u]+a[j].w){
                d[a[j].v] = d[a[j].u] + a[j].w;
                    return true;
        }
    }
    return false;
}
int main()
{
    int icase;

    cin>>icase;
    while(icase--)
    {
        cur  = 0;
        cin>>n>>m>>w;
        while(m--)
        {
            cin>>n1>>m1>>w1;
            a[cur].u = n1;
            a[cur].v = m1;
            a[cur++].w = w1;
            a[cur].u = m1;
            a[cur].v = n1;
            a[cur++].w = w1;
        }
        while(w--)
        {
            cin>>n1>>m1>>w1;
            a[cur].u = n1;
            a[cur].v = m1;
            a[cur++].w = -w1;
        }
        //cout<<INT<<endl;
        if(bellman())puts("YES");
        else
            puts("NO");
    }
}


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