首页 > 其他 > 详细

bellman_ford

时间:2020-04-16 01:19:50      阅读:63      评论:0      收藏:0      [点我收藏+]

bellman_ford算法:有边数限制的最短路,可以处理重边、负边和自环。

给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。

请你求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible。

注意:图中可能 存在负权回路

输入格式

第一行包含三个整数n,m,k。

接下来m行,每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

输出格式

输出一个整数,表示从1号点到n号点的最多经过k条边的最短距离。

如果不存在满足条件的路径,则输出“impossible”。

数据范围

1≤n,k≤500,

1≤m≤10000,

任意边长的绝对值不超过10000。

输入样例:

3 3 1

1 2 1

2 3 1

1 3 3

输出样例:

3

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 510, M = 10001;
int d[N], backup[N];
int n, m, k;
struct edges{
    int a, b, w;
}Edge[M];

int bellman_ford()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    for(int i = 0;i<k;i++)
    {
        memcpy(backup, d, sizeof d);
        for(int j = 0;j < m;j++)//注意这里是要循环结束到m,因为输入的边数就是m。
        {
            int a = Edge[j].a, b = Edge[j].b, w = Edge[j].w;
            d[b] = min(d[b], backup[a] + w);
        }
    }
    if(d[n] > 0x3f3f3f3f / 2) return -1;
    return d[n];
}

int main()
{
    cin>>n>>m>>k;
    for(int i = 0;i<m;i++)
    {
        int a, b, w;
        cin>>a>>b>>w;
        Edge[i] = {a,b,w};
    }
    int t = bellman_ford();
    if(t == -1) cout<<"impossible"<<endl;
    else cout<<t<<endl;
}

限制多少边就循环多少次,放进备份数组里面是为了防止本次循环就发生串联,等到k下一次循环的时候再用重新复制过的备份数组,这样就可以在之前的基础上继续前进 而不会 超出k条边的限制了。

第一次只会更新从起点出发一条边能到达的地方,下一次就更新第二条能到达的,以此递增类推。

k = 1, d[1] = 0, d[2] = 1, d[3] = 3, 这里d[3]不会更新为d[2] + 1,因为用的是上次备份的d[2] +oo

k = 2, d[1] = 0, d[2] = 1, d[3] = min(3, 1 + 1) = 2;

for n 次

  for所有边a, b, w

    dist[b] = min(dist[b], dist[a] + w); //每次无脑的对所有的边进行松弛操作。

bellman_ford

原文:https://www.cnblogs.com/longxue1991/p/12709654.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!