853. 有边数限制的最短路
Posted luyuan-chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了853. 有边数限制的最短路相关的知识,希望对你有一定的参考价值。
给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。
请你求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible。
注意:图中可能 存在负权回路 。
输入格式
第一行包含三个整数n,m,k。
接下来m行,每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。
输出格式
输出一个整数,表示从1号点到n号点的最多经过k条边的最短距离。
如果不存在满足条件的路径,则输出“impossible”。
数据范围
1≤n,k≤5001≤n,k≤500,
1≤m≤100001≤m≤10000,
任意边长的绝对值不超过10000。
输入样例:
3 3 1
1 2 1
2 3 1
1 3 3
输出样例:
3
//贝尔曼算法处理有负权边的图 //整体思路:两重循环,第一重循环循环n次(n表示所有的点数),第二重循环,循环所有的边a,b,w //每重循环更新所有的边dist[b] = min(dist[b],dist[a] + w); ---> 这个更新的操作又叫做松弛操作 //贝尔曼算法证明了---->所有的边一定满数dist[b] <= dist[a] + w(这玩意又叫三角不等式) //如果有负权回路,那么最短路不一定存在,负权回路为负无穷 #include<iostream> #include<algorithm> #include<cstring> using namespace std; //N表示点数,M表示边数 const int N = 510,M = 1e4+10; //n表示n个点,m表示m条边,k表示边数限制 int n,m,k; //距离 int dist[N]; //备份防止串联,避免一个点更新其他点,限制这个点只能用上一个结点迭代的结果 int backup[N]; //定义一个结构体存所有的边 struct{ //a,b表示起点和终点,w表示所有的权重 int a,b,w; }edges[M];//edges表示存所有的边的 int bellman_ford(){ memset(dist,0x3f,sizeof dist); dist[1] = 0; for(int i = 0;i < k;i++){//先从直达开始找最短距离 //对上一个结果进行备份,防止串联使用当前结果 memcpy(backup,dist,sizeof 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);//用上一次迭代的结果更新我们当前的距离 } } //考虑到负权边,所以如果两个正无穷边为负权,有一方较小的情况也会进行更新 //题目给定不超过10000 if(dist[n] > 0x3f3f3f3f / 2){ return -1; }else{ return dist[n]; } } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i = 0;i < m;i++){ int a,b,w; scanf("%d%d%d",&a,&b,&w); edges[i] = {a,b,w}; } int t = bellman_ford(); if(t == -1) puts("impossible"); else printf("%d ",t); return 0; }
以上是关于853. 有边数限制的最短路的主要内容,如果未能解决你的问题,请参考以下文章
AcWing 853. 有边数限制的最短路(bellman的k边限制最短路)
备战蓝桥杯—有边数限制的最短路 (bellman_ford+)——[AcWing]有边数限制的最短路