Bellman-Ford算法和Dijkstra算法

Bellman-Ford算法是通过Relax边来实现的,由于最短无负权回路的路径应该最多有V-1条边,所以一共执行V-1次Relax操作即可,而且注意,每次Relax操作都只是基于上一次Relax操作之后的图,和这次Relax中已经Relax了的节点毫无关系(这个是重点!).
检查负权回路原理:若有负权回路,则经过V-1次relax之后relax还能减小消耗(路径值不会收敛)

bool graph::Bellman_Ford(int start,int res_d[],int res_pre[])
{
    int d[1000];//记录到源点的距离
    int pre[1000];//记录其前驱节点
    for (int i = 0; i < Pnum; i++)//初始化,距离初源点外都为无穷大,源点为0
    {
        if (i == start)
        {
            d[i] = 0;
            pre[i] = i;
        }
        else
        {
            d[i] = INF;
            pre[i] = INF;
        }
    }
    for (int k = 0; k < Pnum - 1; k++)
    {
        for (int i = 0; i < Pnum; i++)
        {
            for (int j = 0; j < edge_set[i].size(); j++)
            {
                int end = edge_set[i][j].end;
                if (d[end] > d[i] + edge_set[i][j].value)//每次松弛的时候仅在上一次的图上进行
                {
                    int a = d[i] + edge_set[i][j].value;
                    res_d[end] = d[i] + edge_set[i][j].value;
                    res_pre[end] = i;
                }
            }
        }
        for (int i = 0; i < Pnum; i++)
        {
            d[i] = res_d[i];
            pre[i] = res_pre[i];
        }
    }
    //检查是否有源可达的负权回路
    for (int i = 0; i < Pnum; i++)
    {
        for (int j = 0; j < edge_set[i].size(); j++)
        {
            int end = edge_set[i][j].end;
            if (d[end] > d[i] + edge_set[i][j].value)//证明还可以松弛,证明最短路径无法收敛,有负权回路
                return false;
        }
    }
    return true;
}

DIjkstra算法:
其仅对与当前的节点相邻的边进行松弛,而每次选松弛后离源点最近的点作为当前节点,并加入到集合中,每一次加入节点u时,此节点u的d[u] = res[u].(反正,假设u是第一个不满足d[u] = res[u]的)

void graph::dijkstra(int start_p,int res[][2])
{
    int p_num = this->Pnum;
    int p = start_p;
    //一共有n - 1个点的距离 
    int visit[1000];
    memset(visit, 0, sizeof(visit));
    visit[p] = 1;
    for (int i = 0; i < p_num - 1; i++)
    {
        int min = INF;
        int min_p;
        for (int j = 0; j < p_num; j++)
        {
            if (edge[p][j] && !visit[j])//p到j有边且j未被访问 ,判断是否更新点j的路径 
            {
                if (res[j][0] == 0 || res[j][0] > res[p][0] + edge[p][j])
                {
                    res[j][0] = res[p][0] + edge[p][j];
                    res[j][1] = p;
                }
            }
            //从所有点中找到到start_p最近的点作为下一个起始点 rea[j][0]证明还没能访问 
            if (!visit[j] && res[j][0] < min && res[j][0] != 0)
            {
                min = res[j][0];
                min_p = j;
            }
        }
        p = min_p;
        visit[p] = 1;
    }
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/z6491679/article/details/46602681
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞