思路:看到题就隐隐约约觉得是搜索,依据当前信息只知道一条线路经过哪些站点,而在某个站点时可以换乘哪些线路缺是不知道的,所有这也是必须有的信息,即在i条线路到达A站后,通过A站可换乘线路,在此线路上到达B站,至此完成回路即 在i->A换j->B,这些换乘和线路信息的至此完成闭合即可开始搜索。
搜索思路
对于采用广度优先:即使用队列进行操作,如果当前站点不是目标站点,则对于当前所在站点,扩展出所有代价为1的可到达的站点,即遍历当前能换乘的线路,这些线路上的所有站点都是代价为1的站点,对这些进行入队,(如果对广度不熟悉建议找个广度搜索的模板看看,主要注意队列元素所在层数即,由第一层扩展出来的节点,层次将会增加,下方代码表现在while内的第一个for循环,用意就在于对队列元素分层处理,不是一股脑的往后,而是遍历完当前层所有队列元素后,对层数标记进行增加,再重复对下一层次进行相同操作),最后需要注意的是如果某个站点或线路已经访问过,就不再继续访问,因为访问了再对其进行访问,这无疑使莫名增加了层次,这对于要求最少是不好的。
对于采用深度优先:采用分支限界,加回溯应该是可以实现的,即某一时刻找到了目标站点,则对其进行层次的记录,如果后续搜索,到达当前层次还没找到则不必再找,没有写代码(后续有机会再补,)
代码
class Solution {
public:
int numBusesToDestination(vector<vector<int>>& routes, int source,
int target) {
if (source == target)
return 0;
int nn = 0;
for (auto& e : routes)
for (auto& ee : e)
nn = max(nn, ee);
if (max(source, target) > nn)
return -1;
vector<vector<int>> station_bus(nn+1);
for (int i = 0; i < routes.size(); i++) {
for (int j = 0; j < routes[i].size(); j++) {
station_bus[routes[i][j]].push_back(i);
}
}
vector<int> station_is(nn+1, 0);
vector<int> bus_is(routes.size(), 0);
queue<int> me;
me.push(source);
station_is[source] = 1;
int ans = 0;
while (!me.empty()) {
int n = me.size();
for (int i = 0; i < n; i++) {
if (me.front() == target) {
// cout<<me.front()<<endl;
return ans;
}
for (int c : station_bus[me.front()]) {
if (bus_is[c])
continue;
for (int k = 0; k < routes[c].size(); k++) {
if (station_is[routes[c][k]]) {
continue;
}
me.push(routes[c][k]);
station_is[routes[c][k]] = 1;
}
bus_is[c] = 1;
}
me.pop();
}
ans++;
}
return -1;
}
};