Bellman-Ford算法及SPFA算法

Bellman-Ford算法能解决存在负权边的单源最短路径问题,还可以判断是否存在负回环

思路和dij一样

1.dis[i] 为源点s到点i的最短路径长度,初始化dis[i]=inf,dis[s] = 0;

2.枚举每一条边(v,u),若dis[u] > dis[v]+w[v][u],dis[u] = dis[v]+w[v][u];

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

#define mem(a) memset(a,0,sizeof(a))
#define ll long long
const int maxn = 100;
const int inf = 0x3f3f3f3f;
int n,m,s,dis[maxn];
struct node
{
    int u,v,w;
}edge[maxn*maxn];

bool Bellman_Ford(int s)
{
    memset(dis,inf,sizeof dis);
    dis[s] = 0;
    bool flag;
    for(int i = 1; i <= n; i++) //n个点
    {
        flag = false;
        for(int j = 0; j < m; j++) //m条边
        {
            int x = edge[j].u;
            int y = edge[j].v;
            int z = edge[j].w;
            if(dis[y] > dis[x]+z)
            {
                dis[y] = dis[x]+z;
                flag = true;
            }
        }
        if(!flag) break;
        if(i==n && flag) return false;//存在负环
    }
    return true;
}
int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0),cout.tie(0);
    scanf("%d%d%d",&n,&m,&s);
    for(int i = 0,x,y,z; i < m; i++) //有向图
    {
        scanf("%d%d%d",&x,&y,&z);
        edge[i].u = x,edge[i].v = y,edge[i].w = z;
    }
    if(Bellman_Ford(s)) printf("%d\n",dis[n]);
    else printf("erro\n");
    return 0;
}
Bellman-Ford

例题  poj-3259

SPFA

1.SPFA 算法详解(最短路径)

2.SPFA算法教学 

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
const int maxn = 600;
const int inf = 0x3f3f3f3f;

struct node
{
    int v,w,next;
} a[maxn*maxn];

bool vis[maxn];
int dis[maxn],pre[maxn],num[maxn];
int n,m,cnt = 0;

void add(int u,int v, int w)
{
    a[cnt].v = v,a[cnt].w = w,a[cnt].next = pre[u];
    pre[u] = cnt++;
}

bool spfa(int s)
{
    queue<int> que;
    mem(vis),mem(num);
    for(int i = 1; i <= n; i++)
    {
        dis[i] = inf;
    }
    dis[s] = 0;
    que.push(s);
    vis[s] = 1; //标记s在队列中
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for(int i = pre[u]; ~i; i = a[i].next)
        {
            int v = a[i].v;
            if(dis[u]+a[i].w < dis[v])
            {
                dis[v] = dis[u]+a[i].w;
                if(!vis[v])
                {
                    que.push(v);
                    vis[v] = 1;
                    num[v]++;
                    if(num[v] >= n)
                        return false;
                }
            }
        }
    }
    return true;
}


int main()
{
    int t,w;
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>w;
        memset(pre,-1,sizeof(pre));
        cnt = 0;
        for(int i = 0,a,b,c; i < m; i++)
        {
            cin>>a>>b>>c;
            add(a,b,c);
            add(b,a,c);
        }
        for(int i = 0,a,b,c; i < w; i++)
        {
            cin>>a>>b>>c;
            add(a,b,-c);
        }
        if(spfa(1)) printf("NO\n"); //不存在
        else printf("YES\n");
    }
}
View Code

 

posted on 2019-10-04 09:53  By_布衣  阅读(233)  评论(0编辑  收藏  举报

导航