第6章第3节-Bellman-Ford-解决负权边

/*对所有的边进行n-1次的松弛操作
检测一个图是否有负权回路:如果在n-1松弛之后最短路仍然会发生变化,则改图必然存在负权回路
在实际操作中,Bellman-Ford算法经常会在未达到n-1轮松弛前就已经计算出最短路,n-1其实是最大值
因此可以添加一个变量check用来标记数组dis在本轮松弛中是否发生了变化,如果没有发生变化,则可以提前跳出循环
*/
#include "stdio.h"
int main()
{
    int dis[10],i,k,n,m,u[10],v[10],w[10],check,flag;
    int inf = 99999999;//用inf(infinity的缩写)存储一个我们认识的无穷大
    //读入n和m,n表示顶点个数,m表示边的条数
    scanf("%d %d",&n,&m);

    //读入边
    for(i = 1;i <= m;i++)
    {
        scanf("%d %d %d",&u[i],&v[i],&w[i]);
    }

    //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    for(i = 1;i <= n;i++)
    {
        dis[i] = inf;
    }
    dis[1] = 0;

    //Bellman-Ford算法核心语句
    for(k = 1;k <= n - 1;k++)
    {
        check = 0;//用来标记在本轮松弛中数组dis是否会发生更新
        //进行一轮松弛
        for(i = 1;i <= m;i++)
        {
            if(dis[v[i]] > dis[u[i]] + w[i])
            {
                dis[v[i]] = dis[u[i]] + w[i];
                check = 1;//数组dis发生更新,改变check的值
            }
        }
        //松弛完毕后检测数组dis是否有更新
        if(check == 0)
        {
            break;//如果数组dis没有更新,提前退出循环结束算法
        }
    }
    //检测负权回路
    flag = 0;
    for(i = 1;i <= m;i++)
    {
        if(dis[v[i]] > dis[u[i]] + w[i])
        {
            flag = 1;
        }    
    }
    if(flag == 1)
    {
        printf("此图含有负权回路" );
    }
    else
    {
        //输出最终结果
        for(i = 1;i <= n;i++)
        {
            printf("%4d",dis[i]);
        }
    }
    getchar();getchar();
    return 0;
}
/*
示例输入:
5 5
2 3 2
1 2 -3
1 5 5
4 5 2
3 4 3
示例输出:
0 -3 -1 2 4
*/

猜你喜欢

转载自blog.csdn.net/perfect_zdq/article/details/89295793