牛客16444题解:BFS解决公交换乘问题
一、问题描述
牛客16444题要求计算从公交站点1到站点n的最少换乘次数。每次乘坐公交车可以到达该线路上的所有站点,换乘次数加1。
二、算法核心思想
三、完整代码实现(带注释)
#include <iostream> #include <vector> #include <queue> #include <unordered_map> #include <unordered_set> using namespace std; const int INF = 1e9; // 定义无穷大值 int main() { ios::sync_with_stdio(false); // 加速输入输出 cin.tie(nullptr); int n, m; // n:站点总数 m:公交线路数 cin >> n >> m; // 建立站点到公交车的映射 unordered_map<int, vector<int>> station_to_buses; // 建立公交车到站点的映射 vector<vector<int>> bus_to_stations(m); // 输入处理:构建双向映射 for (int i = 0; i < m; ++i) { int t; // 当前公交线路的站点数 cin >> t; bus_to_stations[i].resize(t); for (int j = 0; j < t; ++j) { cin >> bus_to_stations[i][j]; station_to_buses[bus_to_stations[i][j]].push_back(i); } } // BFS队列,存储{当前站点,花费} queue<pair<int, int>> q; q.push({1, 0}); // 从站点1出发,初始换乘次数为0 // 记录站点最小花费 vector<int> dist(n + 1, INF); dist[1] = 0; // 起点距离为0 // 记录已经访问过的公交车 vector<bool> visited_bus(m, false); while (!q.empty()) { auto [station, cost] = q.front(); q.pop(); if (station == n) { // 到达终点 cout << cost << endl; return 0; } // 遍历当前站点能乘坐的所有公交车 for (int bus : station_to_buses[station]) { if (visited_bus[bus]) continue; // 跳过已访问的公交线路 visited_bus[bus] = true; // 标记已访问 // 遍历该公交车能到达的所有站点 for (int next_station : bus_to_stations[bus]) { if (dist[next_station] > cost + 1) { // 发现更优路径 dist[next_station] = cost + 1; q.push({next_station, cost + 1}); } } } } cout << -1 << endl; // 无法到达终点 return 0; }
四、关键点解析
双向映射建立:
station_to_buses:快速查询站点可乘哪些公交
bus_to_stations:快速查询公交可达哪些站点
BFS优化:
公交车访问标记避免重复处理
距离数组剪枝减少无效搜索
时间复杂度:
最坏情况O(n*m),但实际运行效率很高
五、实际应用场景
城市公交线路规划
地铁换乘方案
物流配送路径优化
社交网络关系分析
原创内容 转载请注明出处