bellman-ford有边数限制的最短路

196 阅读1分钟

题目思路

本题与Dijkstra算法的最大区别:1、存在负权回路。2、最多经过k条边。

  1. Dijkstra算法无法解决存在负权的最短距离问题,具体原因可以看此篇文章,给出了详细步骤。www.acwing.com/solution/co…
  2. backup数组的作用。为了避免节点最短距离的串连,在有k条边数限制的情况下,我们需要使用上次循环的dist数据,而不能使用本次循环中的dist
  3. 外层循环k次,表示最多只能经过k条边。内层循环m次,将所有的边进行松弛操作。
  4. 最后一步,dist[n] > 0x3f3f3f3f / 2,可能存在dist[n]已经减去一部分的情况。

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 510, M = 10010;

int n, m, k;
int dist[N];
int backup[N];

struct Edge
{
    int a, b, w;
}edge[M];

void bellman_ford()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    for (int i = 0; i < k; i++)
    {
        memcpy(backup, dist, sizeof dist);
        for (int j = 0; j < m; j++)
        {
            auto e = edge[j];
            dist[e.b] = min(dist[e.b], backup[e.a] + e.w);
        }
    }
    if (dist[n] > 0x3f3f3f3f / 2)
    {
        cout << "impossible";
    }
    else
    {
        cout << dist[n];
    }
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> m >> k;
    for (int i = 0; i < m; i++)
    {
        int a, b, w;
        cin >> a >> b >> w;
        edge[i] = { a,b,w };
    }
    bellman_ford();
    return 0;
}