图论--单源最短路 负权边 Bellman-Ford 有边数限制的最短路 java
如果存在负权回路,那么最短路可能不存在(不存在但是能求出一个值,因为这个算法是按迭代次数不停更新的,不存在负回路的点,n次内就能稳定,而对存在负回路的点,则一直更新)
能求出最短路说明不存在负权回路
迭代次数k的实际意义:经过不超过k条边走到每个点的最短路的距离
第n次迭代后,有更新的话,说明存在一条经过n条边的最短路径,那么路径上有n+1个点,而点数总共为n,说明存在负环(自环:权值为负)。(这个算法可以用来找负环,但是一般用spfa来做)
给定一个 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≤500,
1≤m≤10000,
任意边长的绝对值不超过 10000。
输入样例:
3 3 1
1 2 1
2 3 1
1 3 3
输出样例:
3
https://www.acwing.com/problem/content/855/
import java.util.*;
public class Main
{
static int n,m,k,N=505,M=10005,INF=0x3f3f3f3f;
static int dist[]=new int [N],backup[]=new int [N];
static class edge
{
int a,b,w;
public edge(int x,int y,int z)
{
a=x;b=y;w=z;
}
}
static edge es[]=new edge[M];
static int bell_ford()
{
Arrays.setAll(dist, x->INF);
dist[1]=0;
for(int i=0;i<k;++i)
{
backup=dist.clone();
for(int j=0;j<m;++j)
{
int a,b,w;
a=es[j].a;b=es[j].b;w=es[j].w;
dist[b]=Math.min(dist[b], backup[a]+w);
}
}
if(dist[n]>INF/2)return INF;
else return dist[n];
}
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
k=sc.nextInt();
for(int i=0;i<m;++i)
{
int a,b,w;
a=sc.nextInt();
b=sc.nextInt();
w=sc.nextInt();
es[i]=new edge(a,b,w);
}
int t=bell_ford();
if(t==INF)System.out.println("impossible");
else System.out.println(t);
}
}