int dist[N]; // 路线对应已走过的距离,同时具备标记已走过的路线的功能(初始化成无穷大,如果值不是无穷大说明已经走过)
intnumBusesToDestination(vector<vector<int>>& routes, int source, int target){ if (source == target) return0; int len = routes.size(); memset(dist, 0x3f, sizeof dist);
for (int i = 0; i < len; i++) { // 遍历所有路线找到起点 for (auto &x : routes[i]) { if (x == source) { // 找到起始点 q[++tt] = i; // 将对应路线入队 dist[i] = 1; // 至少需要一站路,距离从1开始,将来BFS到其他路线,距离增加1 } hash[x].push_back(i); //将所有点和其所在的路线对应起来 } }
for (; tt >= hh;) { int cur = q[hh++]; for (auto &x : routes[cur]) { if (x == target) return dist[cur]; // 找到目标点,返回距离 // 否则将点对应的所有路线入队,注意跳过已走过的路线,因为已走过的路线及上面所有点必然已经被遍历过一次,点对应的所有路线必然已被入队,避免重复 for (auto &i : hash[x]) { if (dist[i] == 0x3f3f3f3f) { // 新的路线 q[++tt] = i; // 路线入队 dist[i] = dist[cur] + 1; // 将下一个路线距离在本路线基础上+1,顺便标记为已访问 } // 否则是已访问过的路线(已入队或已遍历),直接跳过 } // 将已遍历过的点擦除,道理和标记已访问过的路线一样,只要点被遍历过,那么它对应的所有路线必然已入队。 hash.erase(x); // 将已遍历的点从hashmap中删除,为什么不从别的地方删除? } } return-1; } };