← Все вопросы
Почему мой BFS на сетке даёт TLE, хотя алгоритм правильный?
8
BFS на сетке 1000×1000 правильно находит путь, но получаю TLE/MLE на максимальных тестах. Алгоритм же O(V+E)... Что я делаю не так и как ускорить?
2 ответа
12
✓ Принятый ответ — помог автору
Алгоритм верный, но константа убивает. Типичные причины на больших сетках:
map/setдля visited вместо массива.map<pair<int,int>, int>добавляетlogи огромную константу. Используйте плоскийvector<int> dist(R*C, -1)с индексомr*C + c.- Хранение очереди из строк/пар с лишними копиями. Кодируйте клетку одним
int = r*C + c. - Создание соседей через временный
vector/tupleв каждой итерации. Лучше массивыdr[] = {0,0,1,-1}, dc[] = {1,-1,0,0}. std::endlв выводе (flush каждый раз) — заменяйте на'\n'.
int dr[] = {0,0,1,-1}, dc[] = {1,-1,0,0};
vector<int> dist(R*C, -1);
queue<int> q;
dist[s] = 0; q.push(s);
while (!q.empty()) {
int cur = q.front(); q.pop();
int r = cur / C, c = cur % C;
for (int k = 0; k < 4; k++) {
int nr = r+dr[k], nc = c+dc[k];
if (nr<0||nr>=R||nc<0||nc>=C) continue;
int nx = nr*C + nc;
if (dist[nx] == -1 && grid[nr][nc] != '#') {
dist[nx] = dist[cur] + 1; q.push(nx);
}
}
}
Сложность остаётся O(R·C), но с маленькой константой — проходит.
5
Ещё про MLE: на 10^6 клеток queue<pair<int,int>> или queue<tuple<...>> ест много памяти из-за оверхеда std::deque-блоков. Кодирование клетки в один int и быстрый ввод (scanf/cin с ios::sync_with_stdio(false)) часто и есть разница между TLE и AC. Профилируйте: чаще всего виноват не сам BFS, а структуры-обёртки вокруг него.
Ваш ответ
Войдите, чтобы ответить на вопрос.