• bellman_ford AcWing 853. 有边数限制的最短路


    1. #include
    2. using namespace std;
    3. const int N=510,M=10010;
    4. struct Edge
    5. {
    6. int a,b,w;
    7. }edges[M];
    8. int dist[N];
    9. int backup[N];
    10. int n,m,k;
    11. void bellman_ford()
    12. {
    13. memset(dist,0x3f,sizeof dist);
    14. dist[1]=0;
    15. for(int i=0;i
    16. {
    17. memcpy(backup,dist,sizeof dist);
    18. for(int j=0;j
    19. {
    20. auto t=edges[j];
    21. dist[t.b]=min(dist[t.b],backup[t.a]+t.w);
    22. }
    23. }
    24. }
    25. int main()
    26. {
    27. scanf("%d%d%d",&n,&m,&k);
    28. for(int i=0;i
    29. {
    30. int a,b,w;
    31. scanf("%d%d%d",&a,&b,&w);
    32. edges[i]={a,b,w};
    33. }
    34. bellman_ford();
    35. if(dist[n]>=0x3f3f3f3f/2) puts("impossible");
    36. else printf("%d\n",dist[n]);
    37. return 0;
    38. }

      是一个时间复杂度为km的算法,因为总共两层循环。原理就是更新之后使得满足三角不等式,dist[b]<=dist[a]+w.使用结构体来保存点和边长。首先把距离初始化为正无穷,然后把第一个点的距离初始化为0,题目说了,最多经过k条边,所以循环k次,每一次循环把dist数组存到backup数组里面,主要目的是防止串联。串联的意思是说,假设使用之前更新过的距离,可能会导致因为边数限制(只能最多k条边)距离错误,举例说明就是:1->2->3,1->3,假设k等于1,最多只可以经过一条边,那么我们开始更新完1->2,就不能使用这个更新之后的1->2来更新3,我们要使用没有更新过的距离来更新3.大概是这么个意思。

      然后更新最短距离即可,这个操作称为松弛操作。接着是输入输出,最后有一个问题,为什么是0x3f3f3f3f/2,还是距离说明:假设某个点不可以找到最短路,那么它所对应的最短路是0x3f3f3f3f,假设还有一个点对应的最短路也是0x3f3f3f3f,这两个点之间距离是一个比较小的数字d,那么其中一个点可以表示成0x3f3f3f3f-d,那么就不会输出impossible了,因为我们寻找到它的最短路了,但是实际上它是没有最短路的,发生了矛盾。所以我们需要选取一个比较大的数字,来作为判断标准,笔者试了一下,改成0x3f3f3f3f-5e6作为判断标准也是可以的。

      最后输出的时候,使用

        if(dist[n]>=0x3f3f3f3f-5e6) puts("impossible");

    会比较简洁。 

      只有在特定的题目里面才会使用这个算法,大部分时候都是spfa算法优于这个算法

  • 相关阅读:
    【PostgreSQL】查询30天前的数据
    C++数组指针、函数指针、成员函数指针
    OpenCV笔记--人脸识别算法Eigenfaces和Fisherfaces
    Liteos信号量的使用
    pip-script.py‘ is not present Verifying transaction: failed
    C++逻辑运算符
    PHP反序列化漏洞
    实践 | 大型基金管理公司数据脱敏体系建设
    0201导数的概念-导数与微分-高等数学
    6.3 Case Studies - PIMPL
  • 原文地址:https://blog.csdn.net/L3102250566/article/details/133997626