Skip to content

Commit 3a4c966

Browse files
Create 787. K 站中转内最便宜的航班.md
1 parent ef8eb7b commit 3a4c966

4 files changed

+221
-2
lines changed

Shortest Path/1030 Travel Plan.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#### [1030 Travel Plan](https://pintia.cn/problem-sets/994805342720868352/exam/problems/994805464397627392)
2+
3+
A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.
4+
5+
### Input Specification:
6+
7+
Each input file contains one test case. Each case starts with a line containing 4 positive integers *N*, *M*, *S*, and *D*, where *N* (≤500) is the number of cities (and hence the cities are numbered from 0 to *N*−1); *M* is the number of highways; *S* and *D* are the starting and the destination cities, respectively. Then *M* lines follow, each provides the information of a highway, in the format:
8+
9+
```
10+
City1 City2 Distance Cost
11+
```
12+
13+
where the numbers are all integers no more than 500, and are separated by a space.
14+
15+
### Output Specification:
16+
17+
For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.
18+
19+
### Sample Input:
20+
21+
```in
22+
4 5 0 3
23+
0 1 1 20
24+
1 3 2 30
25+
0 3 4 10
26+
0 2 2 20
27+
2 3 1 20
28+
```
29+
30+
### Sample Output:
31+
32+
```out
33+
0 2 3 3 40
34+
```
35+
36+
---
37+
38+
Dijkstra算法:边有两种代价的情况,另外再使用一个数组记录最小代价的路径,`a[2] = 3` 意为最短路径是由节点 `3` 指向节点 `2` 的,采用方式是因为在求最小代价时**一个点可以有多条出边,但是只能有一条入边**。得到最小代价后深度优先搜索即可。
39+
40+
```java
41+
import java.util.*;
42+
public class Main{
43+
private static final int INF = Integer.MAX_VALUE / 2;
44+
private static int[] dis;
45+
private static int[][] g;
46+
private static int[][] cost;
47+
private static int[] sum_cost;
48+
private static int[] a;
49+
private static boolean[] visited;
50+
private static ArrayList<Integer> arraylist = new ArrayList<>();
51+
52+
public static void dfs(int d, int s){
53+
if(d == s){
54+
arraylist.add(s);
55+
return;
56+
}
57+
dfs(a[d], s);
58+
arraylist.add(d);
59+
}
60+
61+
62+
public static void main(String[] args){
63+
Scanner scanner = new Scanner(System.in);
64+
int N = scanner.nextInt(), M = scanner.nextInt(), S = scanner.nextInt(), D = scanner.nextInt();
65+
dis = new int[N];
66+
g = new int[N][N];
67+
cost = new int[N][N];
68+
sum_cost = new int[N];
69+
visited = new boolean[N];
70+
a = new int[N];
71+
for(int i = 0; i < N; i++){
72+
Arrays.fill(g[i], INF);
73+
Arrays.fill(cost[i], INF);
74+
}
75+
Arrays.fill(dis, INF);
76+
Arrays.fill(sum_cost, INF);
77+
78+
for(int i = 0; i < M; i++){
79+
int temp1 = scanner.nextInt(), temp2 = scanner.nextInt(), temp3 = scanner.nextInt(), temp4 = scanner.nextInt();
80+
g[temp1][temp2] = temp3;
81+
g[temp2][temp1] = temp3;
82+
cost[temp1][temp2] = temp4;
83+
cost[temp2][temp1] = temp4;
84+
}
85+
86+
dis[S] = 0;
87+
sum_cost[S] = 0;
88+
for(int i = 0; i < N; i++){
89+
int cur = -1, min = INF;
90+
for(int j = 0; j < N; j++){
91+
if(!visited[j] && dis[j] < min){
92+
min = dis[j];
93+
cur = j;
94+
}
95+
}
96+
if(cur == -1) return;
97+
visited[cur] = true;
98+
for(int j = 0; j < N; j++){
99+
if(visited[j] == false && g[cur][j] != INF){
100+
if(g[cur][j] + dis[cur] < dis[j]){
101+
dis[j] = dis[cur] + g[cur][j];
102+
sum_cost[j] = cost[cur][j] + sum_cost[cur];
103+
a[j] = cur;
104+
}
105+
else if(g[cur][j] + dis[cur] == dis[j] && cost[cur][j] + sum_cost[cur] < sum_cost[j]){
106+
sum_cost[j] = cost[cur][j] + sum_cost[cur];
107+
a[j] = cur;
108+
}
109+
}
110+
}
111+
112+
}
113+
dfs(D, S);
114+
for(int i = 0; i < arraylist.size(); i++) System.out.print(arraylist.get(i) + " ");
115+
System.out.println(dis[D] + " " + sum_cost[D]);
116+
117+
}
118+
}
119+
```
120+

Shortest Path/743. 网络延迟时间.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class Solution {
6666
while(!minHeap.isEmpty()){
6767
int[] temp = minHeap.poll();
6868
int temp_dis = temp[0], temp_node = temp[1];
69-
if(temp_dis > dis[temp_node]) continue;
69+
if(temp_dis > dis[temp_node]) continue; // pruning
7070
for(int i = 0; i < n; i++){
7171
if(g[temp_node][i] != INF){
7272
if(temp_dis + g[temp_node][i] < dis[i]){
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#### 787. K 站中转内最便宜的航班
2+
3+
难度:中等
4+
5+
---
6+
7+
`n` 个城市通过一些航班连接。给你一个数组 `flights` ,其中 `flights[i] = [fromi, toi, pricei]` ,表示该航班都从城市 `fromi` 开始,以价格 `pricei` 抵达 `toi`
8+
9+
现在给定所有的城市和航班,以及出发城市 `src` 和目的地 `dst`,你的任务是找到出一条最多经过 `k` 站中转的路线,使得从 `src``dst`**价格最便宜** ,并返回该价格。 如果不存在这样的路线,则输出 `-1`
10+
11+
**示例 1:**
12+
13+
```
14+
输入:
15+
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
16+
src = 0, dst = 2, k = 1
17+
输出: 200
18+
解释:
19+
城市航班图如下
20+
21+
22+
从城市 0 到城市 2 在 1 站中转以内的最便宜价格是 200,如图中红色所示。
23+
```
24+
25+
![img](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/16/995.png)
26+
27+
**示例 2:**
28+
29+
```
30+
输入:
31+
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
32+
src = 0, dst = 2, k = 0
33+
输出: 500
34+
解释:
35+
城市航班图如下
36+
37+
38+
从城市 0 到城市 2 在 0 站中转以内的最便宜价格是 500,如图中蓝色所示。
39+
```
40+
41+
![img](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/02/16/995.png)
42+
43+
**提示:**
44+
45+
* `1 <= n <= 100`
46+
* `0 <= flights.length <= (n * (n - 1) / 2)`
47+
* `flights[i].length == 3`
48+
* `0 <= fromi, toi < n`
49+
* `fromi != toi`
50+
* `1 <= pricei <= 10^4`
51+
* 航班没有重复,且不存在自环
52+
* `0 <= src, dst, k < n`
53+
* `src != dst`
54+
55+
---
56+
57+
Dijkstra算法 + 堆优化:将【节点,距离和中转次数】一起存入堆中,如果中转次数小于零则放弃当前情况。如果经过同一点的中转次数少但是距离增大,也需要存入堆中一起考虑,因此不能剪枝(`if(cur_dis > dis[cur_point]) continue;`)。直到堆为空,此时返回 `-1`
58+
59+
```java
60+
class Solution {
61+
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
62+
final int INF = Integer.MAX_VALUE / 2;
63+
int[][] g = new int[n][n];
64+
for(int i = 0; i < n; i++){
65+
Arrays.fill(g[i], INF);
66+
}
67+
for(int[] flight: flights){
68+
g[flight[0]][flight[1]] = flight[2];
69+
}
70+
int[] dis = new int[n];
71+
int[] stops = new int[n];
72+
Arrays.fill(dis, INF);
73+
PriorityQueue<int[]> minHeap = new PriorityQueue<>((a,b) -> (a[0] - b[0]));
74+
minHeap.add(new int[] {0, src, k});
75+
while(!minHeap.isEmpty()){
76+
int[] temp = minHeap.poll();
77+
int cur_dis = temp[0], cur_point = temp[1], cur_stop = temp[2];
78+
if(cur_point == dst) return cur_dis;
79+
if(cur_stop < 0) continue;
80+
// if(cur_dis > dis[cur_point]) continue; // CAN'T DO PRUNING
81+
for(int i = 0; i < n; i++){
82+
if(g[cur_point][i] != INF){
83+
int cost = g[cur_point][i] + cur_dis;
84+
if(cost < dis[i]){
85+
dis[i] = cost;
86+
stops[i] = cur_stop - 1;
87+
minHeap.add(new int[] {cost, i, cur_stop - 1});
88+
}
89+
else if(cur_stop - 1 > stops[i]){
90+
minHeap.add(new int[] {cost, i, cur_stop - 1});
91+
}
92+
}
93+
}
94+
}
95+
return -1;
96+
}
97+
}
98+
```
99+

Shortest Path/882. 细分图中的可到达节点.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class Solution {
7373
while(!pq.isEmpty()){
7474
int[] temp = pq.poll();
7575
int des = temp[0], dis = temp[1];
76-
if(dis > distance[des]) continue;
76+
if(dis > distance[des]) continue; // pruning
7777
for(int i = 0; i < n; i++){
7878
if(g[des][i] != INF){
7979
int new_dis = dis + g[des][i];

0 commit comments

Comments
 (0)