算法训练 最短路
时间限制: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; } } } } } }