算法训练 最短路
时间限制:1.0s 内存限制:256.0MB
问题描述
给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。
输入格式
第一行两个整数n, m。
接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。
输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
-2
数据规模与约定
对于10%的数据,n = 2,m = 2。
对于30%的数据,n <= 5,m <= 10。
对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。
提示: 下面的代码只有70分,超时了!
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import javax.management.Query;
public class Main {
public static Scanner cin = new Scanner(System.in);
public static ArrayList[] v1 = new ArrayList[20005];//v1[i]表示从i到达的点
public static ArrayList[] v2 = new ArrayList[20005];//v1对应路径的权值
public static int visit[] = new int[20005];
public static int d[] = new int[20005];
public static int n, m;
public static void main(String[] args) {
// TODO Auto-generated method stub
n = cin.nextInt();
m = cin.nextInt();
//初始化链表
for(int i = 1; i <= n; i++) {
v1[i] = new ArrayList();
v2[i] = new ArrayList();
}
int a, b, l;
for(int i = 0; i < m; i++) {
a = cin.nextInt();
b = cin.nextInt();
l = cin.nextInt();
v1[a].add(b); //有向图
v2[a].add(l);
}
spfa(1);
for(int i = 2; i <= n; i++) {
System.out.println(d[i]);
}
}
public static void spfa(int s) {
for(int i = 1; i <= n; i++) {
d[i] = 0x3f3f3f3f;
}
d[s] = 0;
visit[s] = 1;
int[] num = new int[20005];
Queue<Integer> mq = new LinkedList<>();
mq.add(s);
num[s] = 1;
while(!mq.isEmpty()) {
int x = mq.peek();
mq.poll();
visit[x] = 0;
int ln = v1[x].size();
for(int i = 0; i < ln; i++) {
int v = (int) v1[x].get(i);
int len = (int) v2[x].get(i);
if(d[v] > d[x] + len) {
d[v] = d[x] + len;
if(visit[v] == 0) {
mq.add(v);
visit[v] = 1;
// num[v]++;
// if(num[v] > n)
// return;
}
}
}
}
}
}