图论--单源最短路 负权边 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);
	}
}
posted @ 2022-11-17 23:03  林动  阅读(39)  评论(0编辑  收藏  举报