题目链接:?1305: 最短路
参考百度百科:?Bellman-Ford算法(我觉得这个写的好点)或?贝尔曼-福特算法
Description
给定一个 n n n个顶点, m m m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从 1 1 1号点到其他点的最短路(顶点从 1 1 1到 n n n编号)。
Input
第一行两个整数
n
n
n,
m
m
m。
接下来的
m
m
m行,每行有三个整数
u
u
u,
v
v
v,
l
l
l,表示
u
u
u到
v
v
v有一条长度为
l
l
l的边。
Output
共 n − 1 n-1 n−1行,第 i i i行表示 1 1 1号点到 i + 1 i+1 i+1号点的最短路。
Sample Input
3 3
1 2 -1
2 3 -1
3 1 2
Sample Output
-1
-2
HINT
数据规模与约定
对于10%的数据,
n
=
2
n=2
n=2,
m
=
2
m=2
m=2。
对于30%的数据,
n
⩽
5
n \leqslant 5
n⩽5,
m
⩽
10
m \leqslant 10
m⩽10。
对于100%的数据,
1
⩽
n
⩽
20000
1 \leqslant n \leqslant 20000
1⩽n⩽20000,
1
⩽
m
⩽
200000
1 \leqslant m \leqslant 200000
1⩽m⩽200000,
−
10000
⩽
l
⩽
10000
-10000 \leqslant l \leqslant 10000
−10000⩽l⩽10000,保证从任意顶点都能到达其他所有顶点。
分析?
感觉这道题就是专门为Bellman-Ford算法而设计的。
- 初始1号点与其他所有点距离为正无穷(47483647),
1号点与自己距离为0,
1号点与以1号点为弧尾的弧的弧头的距离为弧的长度。 - 松弛操作,有n个点,最多循环n-1次,每次遍历所有的边,
如果1号点与弧头的距离大于1号点与弧尾的距离加弧的长度,即
dis[arc[j].head] > dis[arc[j].tail] + arc[j].cost
那么就需要更新1号点与弧头的距离为较小的值,
否则遍历下一条边。 - 直到第i次循环,所有的边都没有进行松弛操作,退出循环。
- 输出1号点与其他点的距离即为最短路。
代码?
/**
* Time 2526ms
* @author wowpH
* @version 1.1
* @date 2019年6月10日上午10:52:40
* Environment: Windows 10
* IDE Version: Eclipse 2019-3
* JDK Version: JDK1.8.0_112
*/
import java.io.InputStreamReader;
import java.util.Scanner;
public class Main {
private final Scanner sc = new Scanner(new InputStreamReader(System.in));
private int n, m; // 顶点数,边数
private int[] dis; // 1号点与i点的距离为dis[i],下标从1开始
private Arc[] arc; // 弧,下标从0开始
public Main() {
while (sc.hasNext()) {
init();// 输入并初始化
relaxation();// 松弛操作
for (int i = 2; i <= n; ++i) {// 输出1号点距离其他点的最短路径
System.out.println(dis[i]);
}
}
sc.close();
}
private void init() {// 输入并初始化
n = sc.nextInt();
m = sc.nextInt();
dis = new int[n + 1];
dis[1] = 0;// 1号点与自己距离为0
for (int i = 2; i <= n; ++i) {
dis[i] = 47483647;// 1号点与i点距离初始化为47483647(正无穷),i>1
}
arc = new Arc[m];// m条弧
for (int i = 0; i < m; ++i) {
arc[i] = new Arc();
arc[i].tail = sc.nextInt();
arc[i].head = sc.nextInt();
arc[i].cost = sc.nextInt();
// 如果弧尾是1号点,那么1号点与弧头的距离为弧权值
if (1 == arc[i].tail) {
dis[arc[i].head] = arc[i].cost;
}
}
}
private void relaxation() {// 松弛操作
boolean flag;// 是否松弛操作
for (int i = 1; i < n; ++i) {// 最多n-1次松弛操作
flag = false;// 未进行松弛操作
for (int j = 0; j < m; ++j) {// 所有边进行松弛操作判断
if (dis[arc[j].head] > dis[arc[j].tail] + arc[j].cost) {
dis[arc[j].head] = dis[arc[j].tail] + arc[j].cost;
flag = true;// 进行了松弛操作
}
}
if (false == flag) {// 未进行松弛操作,结束
break;
}
}
}
public static void main(String[] args) {
new Main();
}
}
class Arc {
int tail;// 弧尾
int head;// 弧头
int cost;// 花费,长度,权值
}
版权声明:
- 转载请于首页注明链接形式的WUSTOJ 1305: 最短路(Java)——wowpH;
- 代码原创,公开引用不能删除首行注释(作者,版本号,时间等信息);
- 如果有疑问欢迎评论区留言,尽量解答;
- 如果有错误,还望大侠评论区指正。