算法——最短路径——Bellman-Ford算法

Bellman-Ford算法

作用:求源点到其他所有点的最短路径,可以处理存在负环的情况
时间复杂度:O(V*E) //V为顶点数,E为边数
原理:
1.用Distans[i]记录源点s到i的距离,首先初始化Distanc,如果存在s到i的边则设Distans[i]=si,如果不存在,则设Distans[i]=无穷,Distans[s]=0。
2.对于n个顶点中的每个顶点u,检测其对于每一条边uv,Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值。
3.为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。

c代码实现

#include
#include
const int maxnum = 100;
const int maxint = 99999; 
// 边
typedef struct Edge{
    int u, v;    // 起点,终点点
    int weight;  // 边的权值
}Edge;

Edge edge[maxnum];     // 保存所有边的值
int  dist[maxnum];     // 结点到源点最小距离

int nodenum, edgenum, source;    // 结点数,边数,源点


void init()
{
    // 输入结点数,边数,源点
    scanf("%d%d%d",&nodenum,&edgenum,&source);
    for(int i=1; i<=nodenum; ++i)
        dist[i] = maxint;
    dist[source] = 0;
    for(int i=1; i<=edgenum; ++i)
    {
        scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].weight);
        if(edge[i].u == source)          //注意这里设置初始情况
            dist[edge[i].v] = edge[i].weight;
    }
}

// 松弛计算
void relax(int u, int v, int weight)
{
    if(dist[v] > dist[u] + weight)
        dist[v] = dist[u] + weight;
}

 bool Bellman_Ford()
{
    for(int i=1; i<=nodenum-1; ++i)
        for(int j=1; j<=edgenum; ++j)
            relax(edge[j].u, edge[j].v, edge[j].weight);
    bool flag = 1;
    // 判断是否有负环路
    for(int i=1; i<=edgenum; ++i)
        if(dist[edge[i].v] > dist[edge[i].u] + edge[i].weight)
        {
            flag = 0;
            break;
        }
    return flag;
}
int main(){
    init();
    if(Bellman_Ford())
        for(int i = 1 ;i <= nodenum; i++)
            printf("%d\n",dist[i]);
    return 0;
} 

你可能感兴趣的:(算法)