Top.Mail.Ru
Ответы
Аватар пользователя
Аватар пользователя
Аватар пользователя
Аватар пользователя
Программирование
+4

Оптимизация DFS. Перебор всех вершин графа.

Есть такая задача:
Дан связный неориентированный невзвешенный граф на n вершинах и n-1 ребре. (Попросту говоря дерево). И есть игрок который перемещается между зданием 1 и зданием 2 (здания = вершины) наикратчайшим путём. При прохождении некоторых рёбер на игрока накладываются негативные эффекты (поштучно, 1 за ребро), и, если негативных эффектов суммарно стало k или больше, игрок умирает. Помогите разработчикам по заданным n, k и информации о рёбрах посчитать общее количество способов расставить здания 1 и 2, чтобы игрок не умер.

Входные данные:
В первой строке записаны числа n и k. (1 <= n <= 10^5 (10 в степени 5), 0 <= k <= 2^15).
В следующих n-1 строках записаны числа u_{i}, v_{i}, b_{i} (1 <= u, v <= n, u != v, 0 <= b <= 1) которые означают существование ребра между вершинами u_{i} и v_{i}. Если b = 1, то на этом ребре игрок получает негативный эффект. (1 штука)

Выходные данные:
Выведите одно число - количество способов выбрать здание 1 и здание 2 так, чтобы игрок не умер.

Ограничение по времени: 2000 мс
Ограничение по памяти: 256 мб

Моё решение основывается на том, что DFS рано или поздно обойдёт все вершины, так как естественных ограничений этому нет, а значит мы можем ограничить его по k. Тогда решение таково, что сколько вершин DFS успел посетить до того, как умер, это количество способов для вершины i. Запустимся от всех -- получим общее количество способов.

Вот код:

123456789101112131415161718192021222324252627282930313233343536373839404142
 #include <iostream> 
#include <vector> 
using namespace std; 
 
const int MAXN = 100005; 
vector<pair<int, int>> graph[MAXN];  
int n, k; 
long long result = 0; 
 
void dfs(int vertex, int parent, int apathy) { 
    for (auto &edge: graph[vertex]) { 
        int nextVertex = edge.first; 
        int road = edge.second; 
 
        if (nextVertex == parent) continue; 
 
        int nextApathy = apathy + (road == 1 ? 1 : 0); 
         
        if (nextApathy <= k) { 
            result++; 
            dfs(nextVertex, vertex, nextApathy); 
        } 
    } 
} 
 
int main() { 
    cin >> n >> k; 
     
    for (int i = 0; i < n - 1; ++i) { 
        int u, v, b; 
        cin >> u >> v >> b; 
        u--; v--;  
        graph[u].push_back({v, b}); 
        graph[v].push_back({u, b}); 
    } 
     
    for (int i = 0; i < n; ++i) { 
        dfs(i, -1, 0); 
    } 
    cout << result << '\n'; 
    return 0; 
}  


Он решает задачу, но он не проходит по времени. Помогите, пожалуйста, оптимизировать. Прагмы в задаче запрещены, пробовал.

По дате
По рейтингу
Аватар пользователя
Мастер

#include <iostream>
#include <vector>
using namespace std;

const int MAXN = 100005;
vector<pair<int, int>> graph[MAXN];
int n, k;
long long result = 0;
bool visited[MAXN] = {false};

void dfs(int vertex, int parent, int& apathy) {
visited[vertex] = true;
for (auto &edge: graph[vertex]) {
int nextVertex = edge.first;
int road = edge.second;

if (nextVertex == parent || visited[nextVertex]) continue;

int nextApathy = apathy + (road == 1 ? 1 : 0);

if (nextApathy <= k) {
dfs(nextVertex, vertex, nextApathy);
result++;
}
}
}

int main() {
cin >> n >> k;

for (int i = 0; i < n - 1; ++i) {
int u, v, b;
cin >> u >> v >> b;
u--; v--;
graph[u].push_back({v, b});
graph[v].push_back({u, b});
}

for (int i = 0; i < n; ++i) {
int apathy = 0;
dfs(i, -1, apathy);
}
cout << result << '\n';
return 0;
}


отпиши, как успехи