在一个有 n 个点, m 个边的有向图中,已知每条边长,求出 1 到 n 的最短路径,返回 1 到 n 的最短路径值。如果 1 无法到 n ,输出 -1
图中可能有重边,无自环。
数据范围:
,
,
5,5,[[1,2,2],[1,4,5],[2,3,3],[3,5,4],[4,5,5]]
9
2,1,[[1,2,4]]
4
两个整数n和m,表示图的顶点数和边数。一个二维数组,一维3个数据,表示顶点到另外一个顶点的边长度是多少每条边的长度范围[0,1000]。
注意数据中可能有重边
import java.util.*; public class Solution { public int findShortestPath (int n, int m, int[][] graph) { int [] visited = new int[n]; int [][] myGraph = new int[n][n]; int[] dp = new int[n]; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ myGraph[i][j] = Integer.MAX_VALUE; } myGraph[i][i] = 0; dp[i] = Integer.MAX_VALUE; } for(int i=0;i<graph.length;i++){ myGraph[graph[i][0]-1][graph[i][1]-1] = Math.min(graph[i][2],myGraph[graph[i][0]-1][graph[i][1]-1]); myGraph[graph[i][1]-1][graph[i][0]-1] = Math.min(graph[i][2],myGraph[graph[i][1]-1][graph[i][0]-1]); } dp[0] = 0; while(true){ int index = findMinIndex(visited,dp); if(index == -1){ break; } visited[index] = 1; for(int j=0;j<n;j++){ if( myGraph[index][j] != Integer.MAX_VALUE ){ dp[j] = Math.min(dp[index] + myGraph[index][j],dp[j]); } } } if(dp[n-1]!=Integer.MAX_VALUE){ return dp[n-1]; }else{ return -1; } } int findMinIndex(int [] visited,int [] dp){ int len = dp.length; int min = Integer.MAX_VALUE; int minIndex = -1; for(int i=0;i<len;i++){ if(dp[i] < min && visited[i]==0){ min = dp[i]; minIndex = i; } } return minIndex; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int 顶点数 * @param m int 边数 * @param graph int二维数组 一维3个数据,表示顶点到另外一个顶点的边长度是多少 * @return int */ public int findShortestPath (int n, int m, int[][] graph) { int[][] edge = new int[n+1][n+1]; int inf = Integer.MAX_VALUE/2; for(int i = 1;i<=n;i++){ Arrays.fill(edge[i],inf); } for(int i = 0;i<m;i++){ edge[graph[i][0]][graph[i][1]] = Math.min(graph[i][2],edge[graph[i][0]][graph[i][1]]); } int[] dist = new int[n+1]; Arrays.fill(dist,-1); for(int i = 2;i<=n;i++){ dist[i] = edge[1][i]; } boolean[] used = new boolean[n+1]; dist[1] = 0; used[1] = true; for(int i = 1;i<n;i++){ int minDist = Integer.MAX_VALUE; int minIndex = 1; for(int j = 2;j<=n;j++){ if(!used[j] && dist[j] != -1 && dist[j]<minDist){ minDist = dist[j]; minIndex = j; } } used[minIndex] = true; for(int j = 1;j<=n;j++){ if(edge[minIndex][j]!=inf){ if(dist[j]!=-1) dist[j] = Math.min(dist[j],dist[minIndex]+edge[minIndex][j]); else dist[j] = dist[minIndex]+edge[minIndex][j]; } } } return dist[n]; // write code here } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param n int 顶点数 * @param m int 边数 * @param graph int二维数组 一维3个数据,表示顶点到另外一个顶点的边长度是多少 * @return int */ public int findShortestPath (int n, int m, int[][] graph) { // write code here int[] distanceArr = new int[n + 1]; Arrays.fill(distanceArr, Integer.MAX_VALUE); boolean[] visited = new boolean[n + 1]; distanceArr[1] = 0; // 自己到自己的距离是0 visited[1] = true; // 自己走过了 for(int i = 2; i <= n; i++){ // 计算1到每个点的最短路 for(int j = 0; j < graph.length; j++){ int from = graph[j][0], to = graph[j][1], edge = graph[j][2]; if(visited[from] && to == i){ distanceArr[to] = Math.min(distanceArr[to], distanceArr[from] + edge); visited[to] = true; } } } return distanceArr[n] == Integer.MAX_VALUE ? -1: distanceArr[n]; } }
import java.util.*; public class Solution { /** * 需要注意重复方向的边,取最短的那条;其次是有些点是不连通的。 * * * @param n int 顶点数 * @param m int 边数 * @param graph int二维数组 一维3个数据,表示顶点到另外一个顶点的边长度是多少 * @return int */ public static int findShortestPath(int n, int m, int[][] graph) { int row = m; boolean[] mark = new boolean[row]; int[] dp = new int[n + 1]; dp[1] = 0; for (int i = 2; i <= n; i++) { dp[i] = -1; } for (int i = 2; i <= n; i++) { for (int j = 0; j < row; j++) { if (!mark[j]) { if (graph[j][1] == i) { if (dp[i] == -1) { if (dp[graph[j][0]] != -1) { dp[i] = dp[graph[j][0]] + graph[j][2]; } } else { if (dp[graph[j][0]] != -1) dp[i] = Math.min(dp[graph[j][0]] + graph[j][2], dp[i]); } mark[j] = true; } } } } return dp[n]; } }
public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * @param n int 顶点数 * @param m int 边数 * @param graph int二维数组 一维3个数据,表示顶点到另外一个顶点的边长度是多少 * @return int */ private int min = Integer.MAX_VALUE; public int findShortestPath (int n, int m, int[][] graph) { int[][] dp = new int[n][n]; for(int[] d : dp){ Arrays.fill(d , Integer.MAX_VALUE); } // 构造图 for(int[] edge : graph){ // 题目有个大坑,就是说可能有重复边,所以在构造边图的时候需要进行一个比较 // (dp[edge[0] - 1][edge[1] - 1] = Math.min(edge[2] , dp[edge[0] - 1][edge[1] - 1]);) // 则不是直接赋值(dp[edge[0] - 1][edge[1] - 1] = edge[2];) dp[edge[0] - 1][edge[1] - 1] = Math.min(edge[2] , dp[edge[0] - 1][edge[1] - 1]); } boolean[] used = new boolean[n]; used[0] = true; dfs(0 , n , 0 , dp , used); return min == Integer.MAX_VALUE ? -1 : min; } public void dfs(int curr ,int n , int dst , int[][] graph ,boolean[] used){ if(curr == n - 1){ min = Math.min(min , dst); return ; } for(int i = 0 ; i < n ; i ++){ // 如果有边可达,并且该点还没被使用 if(graph[curr][i] != Integer.MAX_VALUE && !used[i]){ used[i] = true; dfs(i , n , dst + graph[curr][i] , graph , used); used[i] = false; } } } }
bfs广度优先
public int findShortestPath (int n, int m, int[][] graph) { // write code here List> list = new ArrayList(); for (int i = 0; i < n; i++) { List childList = new ArrayList(); list.add(childList); } for (int[] value : graph) { if(value[1] == value[0]) { continue; } list.get(value[0] - 1).add(value); } int[] arr = new int[n]; Arrays.fill(arr, Integer.MAX_VALUE); arr[0] = 0; Queue queue = new LinkedList(); queue.add(1); while(!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { Integer poll = queue.poll(); List ints = list.get(poll -1); for (int j = 0; j < ints.size(); j++) { if(arr[ints.get(j)[0]-1] + ints.get(j)[2] < arr[ints.get(j)[1]-1]){ arr[ints.get(j)[1] -1] = arr[ints.get(j)[0]-1] + ints.get(j)[2]; queue.add(ints.get(j)[1]); } } } } return arr[n-1] == Integer.MAX_VALUE ? -1 : arr[n-1]; }
public int findShortestPath (int n, int m, int[][] graph) { final int INF = Integer.MAX_VALUE / 2; int[] dp = new int[n]; Arrays.fill(dp, INF); dp[0] = 0; // 重写排序 // 按照起始节点序号升序->距离升序->结束节点升序 进行排序 Arrays.sort(graph, new Comparator<int[]>(){ @Override public int compare(int[] num1, int[] num2){ if (num1[0] != num2[0]){ return num1[0] - num2[0]; }else if (num1[2] != num2[2]){ return num1[2] - num2[2]; }else{ return num1[1] - num2[1]; } } }); for (int[] temp : graph) { // x为起始节点, y为结束节点, dis为x->y的有向距离 int x = temp[0] - 1; int y = temp[1] - 1; int dis = temp[2]; if (dp[x] + dis < dp[y]) { dp[y] = dp[x] + dis; } } return dp[n-1] == INF ? -1 : dp[n-1]; }