c++Ленивый слон по имени Г ни в какую не хочет дел...
Creato il: 10 settembre 2025
Creato il: 10 settembre 2025
c++Ленивый слон по имени Г ни в какую не хочет делать задачу на отбор! Заставить его делать задачи под силу только великому коню по имени М.
Г очень умело ищет причины что-то не делать. В частности, сейчас помеха выглядит следующим образом: Г не может сконцентрироваться, пока не узнает, сколько в его жилье существует простых маршрутов из его комнаты.
Жилье Г можно представить как неориентированный граф с
n
вершинами и
m
ребрами. Комната Г находится в вершине
1
. Дополнительно известно, что ни одна из вершин в таком графе не имеет степень больше
10
(в противном случае Г бы просто не справился ориентироваться в таком сложном жилье).
Определите, сколько существует простых маршрутов (т.е. маршрутов без посещения одной и той же вершины дважды) из вершины
1
. Г еще не знает чисел больше миллиона, поэтому если число простых маршрутов составляет
x
, то выведите
min
(
x
,
10
6
).
Формат входных данных
Первая строка содержит числа
n
(
1
≤
n
≤
2
⋅
10
5
)
и
m
(
0
≤
m
≤
min
(
2
⋅
10
5
,
n
(
n
−
1
)
2
)
)
.
Каждая из следующих
m
строк содержит ребро
(
u
,
v
)
(
1
≤
u
,
v
≤
n
).
Гарантируется, что в графе нет петель и кратных ребер. Обратите внимание, что связность графа не гарантируется.
Формат выходных данных
Выведите одно число —
min
(
x
,
10
6
)
, где
x
— количество простых маршрутов в жилье Г из комнаты
1
.
Примеры
Входные данные
6 4
1 2
1 3
3 4
5 6
Выходные данные
4
Входные данные
5 10
1 2
2 3
3 4
4 5
1 3
2 4
3 5
1 4
2 5
1 5
Выходные данные
65
Вот простой и быстрый способ посчитать количество простых маршрутов из вершины 1 (включая тривиальный маршрут «1»). Используем итеративный DFS с явным стеком и массивом visited. Каждый раз, когда «заходим» в новую вершину (добавляем её в стек), это соответствует уникальному простому маршруту (префиксу пути из 1), поэтому увеличиваем счётчик. Как только счётчик достигает , сразу завершаем.
visited.cpp#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); const long long LIM = 1'000'000; int n, m; if (!(cin >> n >> m)) return 0; vector<vector<int>> g(n + 1); for (int i = 0; i < m; ++i) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } for (int i = 1; i <= n; ++i) sort(g[i].begin(), g[i].end()); // не обязательно, но стабильно vector<char> vis(n + 1, 0); struct Frame { int u; int idx; }; long long ans = 0; // Старт из вершины 1: тривиальный путь «1» vis[1] = 1; ans = 1; if (ans >= LIM) { cout << LIM << "\n"; return 0; } vector<Frame> st; st.push_back({1, 0}); while (!st.empty()) { auto &top = st.back(); int u = top.u; if (top.idx >= (int)g[u].size()) { // откат vis[u] = 0; st.pop_back(); // если есть родитель, он уже инкрементировал свой idx до этого шага // но сам родитель должен оставаться помеченным if (!st.empty()) vis[st.back().u] = 1; continue; } int v = g[u][top.idx++]; if (!vis[v]) { vis[v] = 1; ++ans; if (ans >= LIM) { cout << LIM << "\n"; return 0; } st.push_back({v, 0}); } } cout << ans << "\n"; return 0; }
ans++.ans достигает , выводим и выходим.Сложность по времени ограничена либо количеством простых путей до , либо исчерпанием перебора; по памяти — .