返回列表 發帖

資料結構 404 城市景點(難)

1. 題目說明:
請依下列題意進行作答,使輸出值符合題意要求。

2. 設計說明:
(1) 城市中有 N 個景點(編號為 0 ~ N-1),與 M 條雙向通行的道路,且每一條道路連結兩個景點。

(2) 請撰寫一個程式,讓使用者輸入 M 條連接任兩景點道路資料,找出從景點編號 S 到景點編號 E 所有可能的路徑中,經過景點個數最多的一條路徑(每一條路徑不能重複經過相同景點)。

(3) 若景點個數最多的路徑超過一條,則取景點編號加總最大的路徑。

提示:請使用圖結構搜尋所有路徑。

3. 輸入輸出:
輸入說明
第 1 列:兩個正整數 N、M,其中 N 為景點個數、M 為道路個數。
第 2~M+1 列:每列皆有兩個自然數,為該條道路連接的兩景點編號,共 M 條。
第 M+2 列:兩個自然數 S、E,其中 S 為起始景點編號、E 為結束景點編號。

(所有自然數之間,皆以一個半形空白間隔)

輸出說明
經過景點個數最多的路徑景點編號,編號間以一個半形空白間隔。
(若景點數最多的路徑超過一條,則取景點編號加總最大的路徑)

範例輸入1
6 9
0 1
0 2
0 3
0 4
1 4
2 4
3 4
3 5
4 5
0 5
範例輸出1
0 2 4 3 5
範例輸入2
4 4
0 1
0 2
1 3
2 3
1 3
範例輸出2
1 0 2 3
May

回復 1# may
  1. #include <bits/stdc++.h>
  2. //#include <iostream>
  3. //#include <vector>
  4. //#include <numeric>  // 用於 accumulate 計算數值總和
  5. //#include <algorithm>

  6. using namespace std;

  7. vector<vector<int>> graph; // 存儲無向圖(鄰接表)
  8. vector<int> bestPath;      // 最佳路徑
  9. int maxLength = 0;         // 最長路徑長度
  10. int maxSum = 0;            // 景點編號加總最大值

  11. // 深度優先搜尋(DFS)
  12. void dfs(int node, int end, vector<int>& path, vector<bool>& visited) {
  13.     path.push_back(node);      // 加入當前景點
  14.     visited[node] = true;      // 標記該景點已拜訪

  15.     if (node == end) {  // 抵達終點
  16.         int pathLength = path.size();
  17.         int pathSum = accumulate(path.begin(), path.end(), 0);

  18.         // 更新最佳路徑條件:
  19.         // 1. 若新路徑長度較長,則更新
  20.         // 2. 若長度相同但編號加總較大,也更新
  21.         if (pathLength > maxLength || (pathLength == maxLength && pathSum > maxSum)) {
  22.             maxLength = pathLength;
  23.             maxSum = pathSum;
  24.             bestPath = path;
  25.         }
  26.     } else {  // 繼續探索其他鄰近景點
  27.         for (int neighbor : graph[node]) {
  28.             if (!visited[neighbor]) {  // 確保不重複拜訪
  29.                 dfs(neighbor, end, path, visited);
  30.             }
  31.         }
  32.     }

  33.     path.pop_back();      // 回溯:移除當前景點
  34.     visited[node] = false; // 取消標記
  35. }

  36. int main() {
  37.     int N, M;
  38.     cin >> N >> M;

  39.     graph.assign(N, vector<int>()); // 初始化鄰接表

  40.     // 讀取 M 條道路資訊
  41.     for (int i = 0; i < M; i++) {
  42.         int u, v;
  43.         cin >> u >> v;
  44.         graph[u].push_back(v);
  45.         graph[v].push_back(u); // 雙向通行
  46.     }

  47.     int S, E;
  48.     cin >> S >> E;

  49.     vector<int> path; // 暫存路徑
  50.     vector<bool> visited(N, false); // 紀錄景點是否被拜訪

  51.     dfs(S, E, path, visited); // 執行 DFS

  52.     // 輸出最佳路徑
  53.     for (size_t i = 0; i < bestPath.size(); i++) {
  54.         cout << bestPath[i] << (i == bestPath.size() - 1 ? "\n" : " ");
  55.     }

  56.     return 0;
  57. }
複製代碼
--------------------------------------------------
解題思路
建立圖的鄰接表

使用 vector<vector<int>> graph 來存儲無向圖的連結關係。

使用 DFS(深度優先搜尋)找出所有路徑

透過 DFS 遍歷所有從 S 到 E 的可能路徑,避免重複經過同一個景點。

遇到終點時,根據條件檢查是否更新最佳路徑。

選擇最佳路徑

記錄 最大景點數量 的路徑。

若有多條符合條件的路徑,選擇 景點編號加總較大 的。
測資
測試00
輸入
6 9
0 1
0 2
0 3
0 4
1 4
2 4
3 4
3 5
4 5
0 5
預期輸出
0 2 4 3 5
解釋

所有路徑長度最大為 5

0 → 1 → 4 → 3 → 5(景點總和 = 13)

0 → 2 → 4 → 3 → 5(景點總和 = 14)

選擇編號總和較大的路徑 0 2 4 3 5

測試01
輸入
4 4
0 1
0 2
1 3
2 3
1 3
預期輸出
1 0 2 3
解釋

所有路徑長度最大為 4

0 → 1 → 3 → 2(景點總和 = 6)

1 → 0 → 2 → 3(景點總和 = 6)

景點總和相同,但 1 0 2 3 字典序較大,所以選擇此路徑。

測試 02
輸入
5 5
0 1
1 2
2 3
3 4
0 4
0 4
預期輸出

0 1 2 3 4
解釋

最長路徑:0 → 1 → 2 → 3 → 4(長度 5)

唯一的最長路徑,直接輸出
測試 03
輸入

7 8
0 1
1 2
2 3
3 6
0 4
4 5
5 6
2 5
0 6
預期輸出
0 1 2 5 6
解釋

可能的最長路徑:

0 → 1 → 2 → 3 → 6(景點總和 = 12)

0 → 1 → 2 → 5 → 6(景點總和 = 14)

選擇景點總和較大的 0 1 2 5 6

測試04
輸入
8 10
0 1
1 2
2 3
3 7
0 4
4 5
5 6
6 7
2 6
1 5
0 7
預期輸出
0 1 5 6 7
解釋

可能的最長路徑:

0 → 1 → 2 → 3 → 7(景點總和 = 13)

0 → 1 → 5 → 6 → 7(景點總和 = 19)

選擇景點總和較大的 0 1 5 6 7

這 5 組測資涵蓋 基本測試、分岔選擇、最大景點加總比對 等情境,適用於完整測試程式的正確性。
May

TOP

返回列表