图论之Bellman-Ford

图论之Bellman-Ford

First:
对于一个要参加noip的oier来说,图论是不得不涉及的一大考点,而其中有一个极其重要的算法,即Bellman-Ford。
作为图论入门课程中为数不多的可以针对负权回路的一种算法,Bellman-Ford无疑是迪杰斯特拉之外不得不牢牢掌握的另一算法。

Next:
Bellman-Ford是基于边的一种算法,所以当题目中的边数远小于点数时,即可考虑用边表存储稀疏图再用Bellman-Ford来解决问题。

Then:
那么Bellman-Ford的思想是什么的。
我们知道如果图中出现负权回路的话,迪杰斯特拉算法是错误的。这里需要不断迭代地做“松驰”,直到无“松驰”为止。
那么一个如何判断有没有出现负权回路呢?
由于每次循环都会枚举所有的边,所以每次至少会确定源点到一个点的最短路,这与迪杰斯特拉的思想相似,如此一来,最多只需要进行n-1次迭代即可完成最短路。
即(1)初始化每点到s点的最短距离为∞
(2)取所有边(x,y),看x能否对y松驰。
(3)如果没有任何松驰,则结束break。
(4)如果松驰次数

#include<bits/stdc++.h>
using namespace std;
struct bian
{
    int q,h,v;
}a[7000];
long long d[7000];
bool flag=false;
int f;
int t=0;
int n,m,w;
bool bellman_ford(int st)
{
    memset(d,10,sizeof(d));
    d[st]=0;
    for(int jj=1;jj<=n;++jj)
    {
        flag=0;
        for(int jjj=1;jjj<=t;++jjj)
        {
            if(d[a[jjj].q]+a[jjj].v<d[a[jjj].h])
            {
                d[a[jjj].h]=d[a[jjj].q]+a[jjj].v;
                flag=1;
            }
        }
        if(!flag) 
            return false;
    }
    return true;
}
int main()
{
    cin>>f;
    for(int i=1;i<=f;++i)
    {
        cin>>n>>m>>w;
        for(int j=1;j<=m;++j)
        {
            int x,y,z;
            cin>>x>>y>>z;
            a[++t].q=x;
            a[t].h=y;
            a[t].v=z;
            a[++t].h=x;
            a[t].q=y;
            a[t].v=z;
        }
        for(int j=1;j<=w;++j)
        {
            int x,y,z;
            cin>>x>>y>>z;
            a[++t].q=x;
            a[t].h=y;
            a[t].v=-z;
        }
        if(bellman_ford(a[1].q))
        {
            cout<<"YES"<<endl;
        }
        else cout<<"NO"<<endl;
        t=0;
    }
    return 0;
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/Aico_Huang/article/details/78763327
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞