zoukankan      html  css  js  c++  java
  • 图的最短路径算法 Bellman-Ford算法

    Bellman-Ford算法由美国数学家理查德•贝尔曼(Richard Bellman, 动态规划的提出者)和小莱斯特•福特(Lester Ford)发明。

    适用范围:
    - 有向图,无向图(需把edge重复2遍);
    即对于边w(u, v),存储2遍: w(u,v), w(v,u);
    - 适用于从图中某个固定点,到其他点的最短路径求解;

    算法大致说明:
    1. 初始化所有点,用dis[i]数组存储root点到i点的最短路径;
    2. dis[root]为0,其他的dis[i]用最大值初始化;
    3. 遍历所有的边w(u,v);如果dis[u]+w(uv)的值小于当前的dis[v],则替换之;
    4. pre[i] 保存访问的路径;

    #include<iostream>  
    #include<cstdio>  
    using namespace std;
    
    #define MAX 0x3f3f3f3f  
    #define N 1010  
    int nodenum, edgenum, original; //点,边,起点  
    
    typedef struct Edge //
    {
        int u, v;
        int cost;
    }Edge;
    
    Edge edge[N];
    int dis[N], pre[N];
    
    bool Bellman_Ford()
    {
        for (int i = 1; i <= nodenum; ++i) //初始化  
            dis[i] = (i == original ? 0 : MAX);
        for (int i = 1; i <= nodenum - 1; ++i)  
        for (int j = 1; j <= edgenum * 2; ++j)
        {
            if (dis[edge[j].v] > dis[edge[j].u] + edge[j].cost) //松弛(顺序一定不能反~)  
            {
                dis[edge[j].v] = dis[edge[j].u] + edge[j].cost;
                pre[edge[j].v] = edge[j].u;
            }
        }
        bool flag = 1; //判断是否含有负权回路  
        for (int i = 1; i <= edgenum*2; ++i)
            if (dis[edge[i].v] > dis[edge[i].u] + edge[i].cost)
            {
                flag = 0;
                break;
            }
        return flag;
    }
    
    void print_path(int root) //打印最短路的路径(反向)  
    {
        while (root != pre[root]) //前驱  
        {
            printf("%d-->", root);
            root = pre[root];
        }
        if (root == pre[root])
            printf("%d
    ", root);
    }
    
    int main()
    {
        scanf("%d%d%d", &nodenum, &edgenum, &original);
        pre[original] = original;
        for (int i = 1; i <= edgenum; ++i)
        {
            scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].cost);
            edge[edgenum + i].u = edge[i].v;
            edge[edgenum + i].v = edge[i].u;
            edge[edgenum + i].cost = edge[i].cost;
        }
        if (Bellman_Ford())
            for (int i = 1; i <= nodenum; ++i) //每个点最短路  
            {
                printf("path from %d to %d is: %d
    ", original, i, dis[i]);
                printf("Path:");
                print_path(i);
            }
        else
            printf("have negative circle
    ");
    
        system("pause");
        return 0;
    }

    一个测试用例:

    6 8 6 
    6 5 100
    6 4 30
    6 2 10
    4 5 60
    4 3 20
    3 5 10
    2 3 50
    1 2 5
  • 相关阅读:
    Bootstrap表格
    Bootstrap网格系统
    requestAnimationFrame动画方法
    拖放相关事件
    clientX、pageX、scrollLeft、offsetLeft、clientWidth、screen.width的用法和区别
    嵌套循环中break、continue的用法
    canvas关于getImageData跨域问题解决方法
    js中二维数组的初始化
    chrome/ie中图片底部多出几像素问题
    级联菜单
  • 原文地址:https://www.cnblogs.com/bouygues/p/4773700.html
Copyright © 2011-2022 走看看