/**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;
}
Bellman-ford算法
最新推荐文章于 2024-09-18 20:33:32 发布