Знайдемо топологічне сортування графа. Позначимо через максимальну кількість міст, яке можна відвідати по шляху, починаючи з вершини .
Розглянемо вершини в порядку топологічного сортування. Нехай — поточна вершина. Позначимо через v_1, v_2, ..., v_k вершини, до яких ведуть ребра з . Тоді оновимо значення:
Спочатку встановимо dp[u] = 0~(1 \le u \le n).
Після обробки всіх вершин знаходимо найбільше значення в масиві . Воно дорівнює довжині максимального шляху в графі.
Приклад
Ліворуч наведено граф із першого прикладу. Праворуч — із другого. Найдовші шляхи виділені.
У першому прикладі найдовший шлях дорівнює dp_1 = 3.
У другому прикладі найдовший шлях дорівнює dp_4 = 2.
Реалізація алгоритму
Оголосимо список суміжності графа .
vector<vector<int> > g;Функція dfs виконує пошук у глибину, починаючи з вершини . Сортуємо вершини графа топологічно і записуємо їх в масив .
void dfs(int v)
{
used[v] = 1;
for (int to : g[v])
if (used[to] == 0) dfs(to);
top.push_back(v);
}Основна частина програми. Читаємо вхідні дані. Будуємо список суміжності орієнтованого графа.
scanf("%d %d", &n, &m);
g.resize(n + 1);
while (m--)
{
scanf("%d %d", &a, &b);
g[a].push_back(b);
}Запускаємо пошук у глибину на несв'язаному графі.
used.resize(n + 1);
for (i = 1; i <= n; i++)
if (used[i] == 0) dfs(i);Перебираємо вершини графа в порядку, зворотному до їх топологічного сортування, тобто перебираємо вершини масиву зліва направо.
dp.resize(n + 1);
for (int u : top)
{Шлях з вершини в саму себе має довжину (ініціалізація).
dp[u] = 0;Перебираємо вершини , суміжні з . Розглядаємо ребро .
for (int v : g[u])Для всіх таких вершин шукаємо максимум серед значень dp[v] + 1.
dp[u] = max(dp[u], dp[v] + 1);
}Знаходимо і виводимо найбільший елемент у масиві . Він відповідає довжині найдовшого шляху в графі.
res = *max_element(dp.begin(), dp.end());
printf("%d\n", res);