Bellman-ford算法

在这里插入图片描述

/**BellNman-Ford算法
 * 存边的方式,定义一个结构体
 struct{
     int a,b,w
 }
 比如边有m条的话,就开一个m的数组,也就是edg[m] 
 //然后想遍历所有边的的话,遍历一下当前的结构体就行了
 //算法思想:
  //1.首先迭代n次,也就是for循环n次
  这里需要备份一下
    2.然后第一个for循环里面在嵌套一个for循环
    表示循环所有的边a,b,w,表示存在一条从a走到b的边,权重为w
    //遍历的时候更新方式和dijkstra算法的更新类似
  dist[b]=min(dist[b],dist[a]+w)
  dist[b]<=dist[a]+w
  */
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=510,M=10010;
int n,m,k;
int dist[N],backcup[N];//dist是距离,距离是N
struct Edge //定义一个结构体来存所有边
{
    int a,b,w;  //a,b表示边的起点和终点,w表示边的权重
    
}edges[M];  //edges是存所有边的
//下面就是bellman算法的实质
int bellman_ford()
{
    for(int i=0;i<k:i++)    //因为本题是让求不超过k条边的最短路长度,所以就循环k次
    {
        memcpy(backup,dist,sizeof dist);
        //memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
//函数的格式是:void *memcpy(void *dest, const void *src, size_t n);
//那么这句话就表示成从内存地址存的dist中,拷贝dist现存数组个数的值,来到backup的目标地址里面去
//backup里面存的就是上一次迭代的结果
//相当于通俗理解就是,把dist的值,遍历走一次,然后复制当前位置,当走下一个位置的时候,会重返上一步,
        //上面这句话的意思是防止串联,因为数据更新的时候
        //每次都是在原有的基础上进行更行,不可避免的会造成数据重叠的情况
        for(int j=0;j<m;j++)        //然后在遍历所有边
        {
            int a=edges[j].a,b=edges[j].b,w=edges[j].w;
            dist[b]=min(dist[b],backup[a]+w);
        }
    }
    //最后在判断一下
    if(dist[n]>0x3f3f3f/2)return -1;
    //这里可能有的一个疑惑就是,为什么不直接判断是否等于正无穷,而是正无穷除以2
    //原因是因为这里可能存在负权边,负权边
    return dist[n];
}


int main(){
    scanf("%d%d%d",&n,&m,&k);   //先输入题目中的n,m,k
    for(int i=0;i<m;i++)  //读入m条边        
    {
        int a,b,w;
        scanf("%d%d%d",&n,&m,&w);
        edes[i]={a,b,w};    //存一下几个值
    }
        int t=bellman_ford();   //然后这里使用一个变量t来接bellman这个算法,进行调用
        if(t==-1)puts("impossible");
        else printf("%d\n",t);
        //如果不为-1,那么就输出这个算法东西,否则就输出个impossible
        return 0}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值