典型的迪杰斯特拉,这个题目有两个坑,看了discuss才AC
1.图是无向的。
2.边有重复的,要取最小的
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.PriorityQueue;
public class Main{
public static int N;//顶点的个数
public static int[] shortPathLen ; // 保存start到其他各点的最短路径
public static LinkedList<Edge2387> [] list;
static int _MAX=2087654321;
public static void main(String[] args) throws Exception{
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
String[] str=reader.readLine().split(" ");
int T=Integer.parseInt(str[0]);//第一个是边数
N=Integer.parseInt(str[1])+1;//第二个是顶点个数
list=new LinkedList[N];
for (int i = 0; i < N; i++) {
list[i]=new LinkedList<Edge2387>();
}
for (int i = 0; i < T; i++) {
str=reader.readLine().split(" ");
int start=Integer.parseInt(str[0]);
int to=Integer.parseInt(str[1]);
int dis=Integer.parseInt(str[2]);
list[start].add(new Edge2387(start,to,dis));
list[to].add(new Edge2387(to,start,dis));
}
shortPathLen=new int[N];
for(int i=0;i<shortPathLen.length;i++){
shortPathLen[i]=_MAX;
}
int begin=1;
proceeDS(list,begin);
System.out.println(shortPathLen[N-1]);
reader.close();
}
public static void proceeDS(LinkedList<Edge2387> [] list,int begin){//begin 代表起点
shortPathLen[begin]=0;
PriorityQueue<Edge2387> pq=new PriorityQueue<Edge2387>();
Edge2387 e=new Edge2387(begin,begin,0);
pq.add(e);
while( ! pq.isEmpty() ){
Edge2387 startEdge=pq.poll();//弹出最小的路径(不是点),初始情况可以理解为自己到自己
for (Edge2387 et:list[startEdge.to]) {// 这条路径被选择后,这条路径的终结点相连的路径也要被加进来,然后下一轮继续,et是终结点相连的边
if( shortPathLen[et.to]>shortPathLen[et.start]+et.dis) {//能松弛的才需要加入进来
shortPathLen[et.to] = shortPathLen[et.start] + et.dis;//松弛操作
pq.add(et);
}
}
}
}
}
class Edge2387 implements Comparable<Edge2387> {
public Edge2387( int start,int to, int dis) {
this.start=start;
this.to = to;
this.dis = dis;
}
public int to;
public int dis;
public int start;
@Override
public int compareTo(Edge2387 o) {
return this.dis-o.dis;
}
}
这个题目使用二维矩阵也能过
package info.frady.algo;
import java.io.BufferedReader;
import java.io.InputStreamReader;
/**
* meng3.wei 20200426
* 基本的迪杰斯特拉
*/
public class POJ2387 {
public static final int M = 1000000000; // 代表正无穷
public static int n;//顶点的个数
public static int[] shortPathLen ; // 保存start到其他各点的最短路径
public static boolean [] visited;
public static int[] pid;
public static void main(String[] args) throws Exception{
// 二维数组每一行分别是 A、B、C、D、E 各点到其余点的距离,
// A -> A 距离为0, 常量M 为正无穷
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
String[] str=reader.readLine().split(" ");
int T=Integer.parseInt(str[0]);//第一个是边数
n=Integer.parseInt(str[1])+1;//第二个是顶点个数
int[][] weight1 = new int[n][n];
for (int i = 0; i <n ; i++) {
for (int j = 0; j <n ; j++) {
weight1[i][j]=M;
}
}
for (int i = 0; i < T; i++) {
str=reader.readLine().split(" ");
int start=Integer.parseInt(str[0]);
int end=Integer.parseInt(str[1]);
int len=Integer.parseInt(str[2]);
if(weight1[start][end]>len ){//注意这块是无向图,并且边要去重
weight1[start][end]=len;
weight1[end][start]=len;
}
}
pid=new int[n];
visited=new boolean[n];
shortPathLen=new int[n];
int be=1;
proceeDS(weight1,be);
System.out.println(shortPathLen[n-1]);
/*for (int i = 1; i < n; i++) {
System.out.println("从" + be + "出发到" + i + "的最短距离为:" + shortPathLen[i]);
int p=pid[i];
StringBuffer sb=new StringBuffer();
sb.append(i);
while(p!=be){
sb.append(">--"+p);
p=pid[p];
}
sb.append(">--"+be);
System.out.println(sb.reverse());
}*/
reader.close();
}
public static void proceeDS(int[][] weight1,int be){//be代表起点
pid[be]=be;
visited[be]=true;
shortPathLen[be]=0;
for (int i = 1; i < n-1; i++) {
int minLen=M;
int s1=0;
for (int end = 1; end <n ; end++) {//1.找出距离最小的点s1 这块我其实有个疑问,如果be这个顶点和别的点都不连接,那么这块计算不下去了?
if(!visited[end] && weight1[be][end]<minLen ){
s1=end;
minLen=weight1[be][end];
}
}
shortPathLen[s1]=minLen;
visited[s1]=true;
for (int e1 = 1; e1<n ; e1++) {//2.根据s1到它连接的每一个e1,如果 (开始节点->s1)+(s1->e1)<(开始节点->e1) 那么开始节点->e1需要更新一下
if( !visited[e1] && (weight1[be][s1]+ weight1[s1][e1] <weight1[be][e1]) ){
weight1[be][e1]=weight1[be][s1]+ weight1[s1][e1];
pid[e1]=s1;
}
}
}
}
}