From 5a88e74f703bf2cb277d5d77313f31a807453ce0 Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:24:20 +0000 Subject: [PATCH 1/8] 4 points from first paragraph --- doc/Paragraph_1.md | 110 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 doc/Paragraph_1.md diff --git a/doc/Paragraph_1.md b/doc/Paragraph_1.md new file mode 100644 index 0000000..715cc5e --- /dev/null +++ b/doc/Paragraph_1.md @@ -0,0 +1,110 @@ + + +### 1.1. Ориентированный граф, псевдограф. Неориентированный граф, псевдограф. Связность в неор. графе, компоненты связности. Слабая и сильная связность в ор. графе. Компоненты слабой, сильной связности. + $\textbf{1.1.1 Граф}$ - упорядоченная пара $G$($V$, $E$), где $V$ - множество вершин, а $E$ $\subset$ ($V$ x $V$) - ребра. \ + \ + $\textbf{1.1.2 Ориентированный граф}$ - граф, в котором у каждого ребра есть направление, то есть стартовая и конечная вершины. \ + \ + $\textbf{1.1.3 Мультиграф}$ - граф, в котором хотя бы одна пара вершин соединена более чем одним ребром. \ + \ + $\textbf{1.1.4 Псевдограф}$ Псевдограф - мультиграф, в котором есть петли. \ + \ + $\textbf{1.1.5}$ Две вершины $u$ и $v$ **достижимы**, если найдется такая цепь из вершин $v$, $v_1$, $v_2$, ..., $v_n$, $u$, что $v_i$ смежна с $v_{i+1}$, а также смежны $v$, $v_1$ и $v_n$, $u$. \ + \ + $\textbf{1.1.6}$ Неориентированный граф **связен**, если для любой вершины все остальные достижимы из нее.\ + \ + $\textbf{1.1.7 Компонента связности в графе}$ - множество вершин графа достижимых попарно и рёбра их связывающие.\ + \ + $\textbf{1.1.8 Слабая связность в ориентированном графе}$ - ориентированный граф не связен, но его неориентированная копия связна.\ + \ + $\textbf{1.1.9 Сильная связность в оринетированном графе}$ - достижимость из произвольной вершины графа в любую другую.\ + \ + $\textbf{1.1.10 Компонента сильной связности в графе G}$ - подграф $G'$, который сильно связан.\ + \ + $\textbf{1.1.11 Компонента слабой связности в графе G}$ - подграф $G'$, который слабо связан. \ +### 1.2. Обход в глубину. Цвета вершин. Времена входа и выхода. Лемма о белых путях(с доказательством). + \ + $\textbf{1.2.1 Обход в глубину (DFS)}$ - это рекурсивный алгоритм по поиску всех вершин графа или дерева. Обход подразумевает под собой посещение всех вершин графа.\ + \ + $\quad$ **Алгоритм:** \ + $\quad$ $\quad$ $1.$ Выбираем любую вершину $v$ из еще не посещенных. \ + $\quad$ $\quad$ $2.$ Помечаем ее как пройденную. \ + $\quad$ $\quad$ $3.$ Повторяем первые два шага к смежным к $v$ вершинам. \ + \ + $\textbf{1.2.2 Цвета вершин в DFS}$ \ + $\quad$ **Белый** - вершина еще не была посещена. \ + $\quad$ **Серый** - вершина в процессе обхода. \ + $\quad$ **Черный** - вершина, у которой посещены все смежные ей вершины. \ + \ + $\textbf{1.2.3 Времена входа и выхода в DFS}$ - назовем временами входа и выхода пару чисел $entry[u], leave[u]$. Массивы $leave$ и $entry$ будем заполнять в ходе модифицированного DFS. \ + \ + $\textbf{1.2.4 Модифицированный DFS.}$ + \ + $\quad$ **Алгоритм:** \ + $\quad$ $\quad$ $1.$ Все вершины в начале алгоритма белые. \ + $\quad$ $\quad$ $2.$ Заводим переменную $time = $ 0. \ + $\quad$ $\quad$ $3.$ Выберем произвольную вершину $u$, $entry[u] = time$. \ + $\quad$ $\quad$ $4.$ Красим вершину $u$ в серый цвет, инкрементируем $time$. \ + $\quad$ $\quad$ $5.$ Для каждой белой вершины, смежной с $u$, запускаем DFS. \ + $\quad$ $\quad$ $6.$ Красим $u$ в черный цвет, инкременитруем $time$, $leave[u] = time$. \ + \ + $\textbf{1.2.5 Лемма о белых путях.}$ \ + $\quad$ Пусть дан граф $G$. Запустим DFS($G$). Остановим выполнение процедуры DFS от какой-то вершины $u$ в тот момент, когда вершина $u$ была выкрашена в серый цвет (назовем первым моментом времени). Заметим, что в данный момент в графе $G$ есть как белые, так и черные и серые вершины. Продолжим выполнение процедуры DFS($u$) до того момента, когда вершина $u$ станет черной (второй момент времени). Тогда вершины графа $G$ \ {$u$}, бывшие черными и серыми в первый момент времени, не поменяют свой цвет ко второму моменту времени, а белые вершины либо останутся белыми, либо станут черными, причем черными станут те, что были достижимы от вершины $u$ по белым путям. \ + + **Доказательство:** \ + $\quad$ Черные вершины останутся черными, потому что цвет может меняться только + по схеме белый, серый, черный. Серые останутся серыми, потому что они лежат в стеке рекурсии и + там и останутся. \ + \ + $\quad$ Заметим, что не существует такого момента в процессе обхода, что существует ребро из черной $v$ + вершины в белую $u$. Действительно, запустим DFS($v$). В этот момент $v$ стала серой, а 𝑢 была белой. + Далее будет запущен DFS($u$), так как $u$ была белой. По алгоритму вершина $v$ будет покрашена в + черный цвет тогда, когда завершится обход всех вершин, достижимых из нее по одному ребру, кроме + тех, что были рассмотрены раньше нее. Таким образом, вершина $v$ может стать черной только тогда, + когда DFS выйдет из вершины $u$, и она будет покрашена в черный цвет. Получаем противоречие. \ + \ + $\quad$ Теперь заметим, что если вершина достижима по пути из белых вершин в первый момент времени, + то она стала черной ко сторому моменту времени (из абзаца выше следует). + Заметим, что это верно и в обратную сторону. Рассмотрим момент, когда вершина $v$ стала черной: + в этот момент существует cерый путь из $u$ в $v$, а это значит, что в первый момент времени сущестовал + белый путь из $u$ в $v$. \ + \ + $\quad$ Отсюда следует, что если вершина была перекрашена из белой в черную, то она была достижима + по белому пути, и что если вершина как была, так и осталась белой, она не была достижима по + белому пути, что и требовалось доказать. \ + ### 1.3. Проверка связности неориентированного графа. Поиск цикла в неориентированном и ориентированном графе. Топологическая сортировка. + $\textbf{1.3.1 Проверка связности ориентированного графа.}$ - модифицируем DFS так, чтобы он возвращал число посещенных вершин. Тогда запустим его от произвольной вершины, и если возвращенное число равно числу вершин в графе, то граф связный. \ + \ + $\textbf{1.3.2 Поиск цикла в неориентированном и ориентированном графе.}$ \ + $\quad$ Будем решать задачу с помощью поиска в глубину. \ + \ + $\quad$ В случае ориентированного графа произведём серию обходов. То есть из каждой вершины, в + которую мы ещё ни разу не приходили, запустим поиск в глубину, который при входе в вершину + будет красить её в серый цвет, а при выходе из нее — в чёрный. И, если алгоритм пытается пойти в + серую вершину, то это означает, что цикл найден. \ + \ + $\quad$ В случае неориентированного графа, одно ребро не должно встречаться в цикле дважды по определению. Поэтому необходимо дополнительно проверять, что текущее рассматриваемое из вершины + ребро не является тем ребром, по которому мы пришли в эту вершину. \ + \ + $\textbf{1.3.3 Топологическая сортировка.}$ \ + $\quad$ Топологическая сортировка ориентированного ациклического графа $G(V, E)$ представляет собой + упорядочивание вершин таким образом, что для любого ребра ($u$, $v$) $\in$ $E$ номер вершины 𝑢 меньше + номера вершины $u$. \ + \ + $\quad$ Предположим, что граф ацикличен, т.е. решение существует. Что делает обход в глубину? При + запуске из какой-то вершины $v$ он пытается запуститься вдоль всех рёбер, исходящих из $v$. Вдоль + тех рёбер, концы которых уже были посещены ранее, он не проходит, а вдоль всех остальных — + проходит и вызывает себя от их концов. \ + \ + $\quad$ Таким образом, к моменту выхода из вызова DFS($v$) все вершины, достижимые из $v$ как непосредственно (по одному ребру), так и косвенно (по пути)— все такие вершины уже посещены обходом. Следовательно, если мы будем в момент выхода из DFS($v$) добавлять нашу вершину в начало некоего списка, то в конце концов в этом списке получится топологическая сортировка. \ + ### 1.4. Нахождение компонент сильной связности. Алгоритм Косарайю. Алгоритм Тарьяна. + \ + $\textbf{1.4.1 нахождение компонент сильной связности. Алгоритм Косарайю}$ \ + $\quad$ **Алгоритм :** \ + $\quad$ $\quad$ $1.$ Строим граф $H$ на основе данного графа $G$, инвертируя все ребра. \ + $\quad$ $\quad$ $2.$ Запускаем DFS на этом графе, вычисляющий для каждой вершины время выхода DFS из нее. Пусть эти данные будут находиться в массиве $outTime$. \ + $\quad$ $\quad$ $3.$ Выполняем DFS на исходном графе, перебирая вершины в порядке убывания $outTime[u]$. \ + \ + Подробнее про работу алгоритма рассказывается в этом видео: https://www.youtube.com/watch?v=-UgiBh1IMQU&t=704s \ + \ + From 6d4054a5f25476da1ac083a2891baf2dccb55029 Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Sat, 13 Jan 2024 16:54:56 +0000 Subject: [PATCH 2/8] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=201,?= =?UTF-8?q?=204,=205=20=D0=B7=D0=B0=D0=B4=D0=B0=D1=87=D1=83=20=D1=81=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- task_01/src/main.cpp | 23 ++++++- task_01/src/test.cpp | 56 +++++++++++++++- task_01/src/topology_sort.cpp | 27 ++++++++ task_01/src/topology_sort.hpp | 6 ++ task_04/src/Deijkstra.cpp | 35 ++++++++++ task_04/src/Deijkstra.hpp | 4 ++ task_04/src/main.cpp | 24 ++++++- task_04/src/test.cpp | 118 +++++++++++++++++++++++++++++++++- task_05/src/RMQ.cpp | 37 +++++++++++ task_05/src/RMQ.hpp | 8 +++ task_05/src/main.cpp | 26 +++++++- task_05/src/test.cpp | 33 +++++++++- 12 files changed, 388 insertions(+), 9 deletions(-) create mode 100644 task_04/src/Deijkstra.cpp create mode 100644 task_04/src/Deijkstra.hpp create mode 100644 task_05/src/RMQ.cpp create mode 100644 task_05/src/RMQ.hpp diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index 0e4393b..a38f0cb 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1,3 +1,24 @@ #include +#include +#include +#include +#include "topology_sort.hpp" -int main() { return 0; } + + + +int main () { + int n, m; + std::cin >> n >> m; + + std::vector< std::vector > graph; + graph.resize(n); + int tmp_from, tmp_to; + for (int i = 0; i < m; ++i) { + std::cin >> tmp_from >> tmp_to; + graph[tmp_from].push_back(tmp_to); + } + + std::vector vec = top_sort(graph); + +} \ No newline at end of file diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index ef5a86a..a40a732 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -4,5 +4,59 @@ #include "topology_sort.hpp" TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] + std::vector< std::vector > graph = {{2, 5, 4}, + {3, 5, 6}, + {}, + {2}, + {}, + {2, 3, 4}, + {3}, + {5}}; + std::vector ans = {7, 1, 6, 0, 5, 4, 3, 2}; + ASSERT_EQ(top_sort(graph), ans); } + + +TEST(TopologySort, Cycle) { + std::vector< std::vector > graph = {{1}, + {2}, + {0, 1, 2}, + {}}; + std::vector ans = {3, 0, 1, 2}; + ASSERT_EQ(top_sort(graph), ans); +} + +TEST(TopologySort, Empty_graph) { + std::vector< std::vector > graph = {{0}}; + std::vector ans = {0}; + ASSERT_EQ(top_sort(graph), ans); +} + +TEST(TopologySort, Full_graph_with_loops) { + std::vector< std::vector > graph = {{0, 1, 2}, + {0, 1, 2}, + {0, 1, 2}}; + std::vector ans = {0, 1, 2}; + ASSERT_EQ(top_sort(graph), ans); +} + +TEST(TopologySort, BIK_graph) { + std::vector< std::vector > graph = {{1, 2, 3}, + {5}, + {5}, + {4, 5}, + {6, 8}, + {4, 6, 7}, + {9}, + {9}, + {7, 9}, + {}}; + std::vector ans = {0, 3, 2, 1, 5, 4, 8, 7, 6, 9}; + ASSERT_EQ(top_sort(graph), ans); +} + +TEST(TopologySort, Isolated_verticles) { + std::vector> graph = {{1, 2, 3}, {0}, {1}, {2}, {}, {4}}; + std::vector res = {5, 4, 0, 3, 2, 1}; + ASSERT_EQ(top_sort(graph), res); +} \ No newline at end of file diff --git a/task_01/src/topology_sort.cpp b/task_01/src/topology_sort.cpp index e53f670..84eb0ff 100644 --- a/task_01/src/topology_sort.cpp +++ b/task_01/src/topology_sort.cpp @@ -1 +1,28 @@ #include "topology_sort.hpp" +#include + +void dfs (int v, std::vector &used, std::vector &result, std::vector< std::vector > &graph) { + used[v] = true; + for (int i = 0; i < graph[v].size(); ++i) { + int to = graph[v][i]; + if(!used[to]) + dfs(to, used, result, graph); + } + + result.push_back(v); +} + +std::vector top_sort (std::vector< std::vector > &graph) { + std::vector used; + used.resize(graph.size()); + + std::vector result; + for (int i = 0; i < graph.size(); ++i) { + if (!used[i]) + dfs(i, used, result, graph); + } + + reverse(result.begin(), result.end()); + + return result; +} \ No newline at end of file diff --git a/task_01/src/topology_sort.hpp b/task_01/src/topology_sort.hpp index 6f70f09..b37e586 100644 --- a/task_01/src/topology_sort.hpp +++ b/task_01/src/topology_sort.hpp @@ -1 +1,7 @@ #pragma once +#include + + +void dfs (int v, std::vector &used, std::vector &result, std::vector< std::vector > &graph); + +std::vector top_sort (std::vector< std::vector > &graph); \ No newline at end of file diff --git a/task_04/src/Deijkstra.cpp b/task_04/src/Deijkstra.cpp new file mode 100644 index 0000000..f7fc999 --- /dev/null +++ b/task_04/src/Deijkstra.cpp @@ -0,0 +1,35 @@ +#include "Deijkstra.hpp" +#include + +const int INF = 1e9; + +int Deijkstra(int start, int end, std::vector< std::vector< std::pair > > &graph) { + + if (end >= graph.size() or start < 0) { throw "Bad Input"; } + + if (graph.size() == 0) throw "Empty Graph"; + + std::vector dist(graph.size(), INF); + dist[start] = 0; + std::vector used(graph.size()); + + for(int i = 0; i < graph.size(); ++i) { + int closest = -1; + for(int j = 0; j < graph.size(); ++j) { + if (!used[j] && (closest == -1 || dist[closest] > dist[j])) { + closest = j; + } + } + + used[closest] = true; + + for(auto &[to, weight] : graph[closest]) { + if (weight < 0) throw "Negative Weight!"; + if (dist[to] > dist[closest] + weight) { + dist[to] = dist[closest] + weight; + } + } + } + if (dist[end] == INF) throw "No path to this verticle!"; + return dist[end]; +} \ No newline at end of file diff --git a/task_04/src/Deijkstra.hpp b/task_04/src/Deijkstra.hpp new file mode 100644 index 0000000..683da2a --- /dev/null +++ b/task_04/src/Deijkstra.hpp @@ -0,0 +1,4 @@ +#pragma once +#include + +int Deijkstra(int start, int end, std::vector< std::vector< std::pair > > &graph); \ No newline at end of file diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 0e4393b..bbcacdf 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -1,3 +1,25 @@ #include +#include +#include "Deijkstra.hpp" -int main() { return 0; } +using namespace std; + +int main () { + int n, m; + cin >> n >> m; + + vector< vector< pair > > graph; + graph.resize(n); + + int from, to, weight; + + for(int i = 0; i < m; ++i) { + cin >> from >> to >> weight; + graph[from].push_back( {to, weight} ); + } + + int start, end; cin >> start >> end; + int k = Deijkstra(start, end, graph); + + cout << k; +} \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 5e11617..0588df6 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,6 +1,118 @@ - #include +#include "Deijkstra.hpp" + +TEST(Deijkstra, Test_default_graph_1) { + std::vector< std::vector< std::pair > > graph = {{{1, 1}, {8, 1}}, + {{2, 1}}, + {{4, 1}}, + {{2, 1}, {4, 1}}, + {}, + {{7, 1}}, + {{5, 1}, {7, 1}}, + {{2, 1}, {4, 1}}, + {{6, 1}, {9, 1}}, + {{6, 1}}}; + ASSERT_EQ(Deijkstra(0, 4, graph), 3); +} + +TEST(Deijkstra, Test_default_graph_2) { + std::vector< std::vector< std::pair > > graph = {{{1, 10}, {2, 7}}, + {{4, 3}, {3, 9}}, + {{3, 11}, {5, 2}}, + {{6, 8}, {7, 12}, {8, 1}}, + {{6, 4}}, + {{8, 5}}, + {{9, 6}}, + {{9, 13}}, + {{9, 8}}, + {}}; + ASSERT_EQ(Deijkstra(0, 9, graph), 22); +} + +TEST(Deijkstra, Test_default_graph_3) { + std::vector< std::vector< std::pair > > graph = {{{1, 2}, {2, 2}, {5, 3}}, + {{2, 1}, {3, 2}, {6, 8}}, + {{3, 1}, {5, 4}}, + {{6, 3}, {4, 2}}, + {{5, 4}, {7, 6}}, + {{7, 7}}, + {{7, 8}}, + {}}; + ASSERT_EQ(Deijkstra(0, 7, graph), 10); +} + +TEST(Deijkstra, Test_default_graph_4) { + std::vector< std::vector< std::pair > > graph = {{{1, 10}, {3, 8}, {4, 31}}, + {{2, 7}}, + {{3, 9}, {7, 27}}, + {{5, 11}}, + {{6, 32}}, + {{6, 17}, {8, 15}}, + {{8, 21}}, + {{8, 15}}, + {}}; + ASSERT_EQ(Deijkstra(0, 3, graph), 8); +} + +TEST(Deijkstra, Test_check_for_bad_input_1) { + std::vector< std::vector< std::pair > > graph = {{{1, 10}, {2, 7}}, + {{4, 3}, {3, 9}}, + {{3, 11}, {5, 2}}, + {{6, 8}, {7, 12}, {8, 1}}, + {{6, 4}}, + {{8, 5}}, + {{9, 6}}, + {{9, 13}}, + {{9, 8}}, + {}}; + ASSERT_ANY_THROW(Deijkstra(0, 10, graph)); +} + +TEST(Deijkstra, Test_check_for_bad_input_2) { + std::vector< std::vector< std::pair > > graph = {{{1, 10}, {2, 7}}, + {{4, 3}, {3, 9}}, + {{3, 11}, {5, 2}}, + {{6, 8}, {7, 12}, {8, 1}}, + {{6, 4}}, + {{8, 5}}, + {{9, 6}}, + {{9, 13}}, + {{9, 8}}, + {}}; + ASSERT_ANY_THROW(Deijkstra(-6, 9, graph)); +} + +TEST(Deijkstra, Test_empty_graph) { + std::vector< std::vector< std::pair > > graph = {}; + ASSERT_ANY_THROW(Deijkstra(0, 9, graph)); +} -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(Deijkstra, Test_default_graph_with_negative_weights) { + std::vector< std::vector< std::pair > > graph = {{{1, 1}, {8, 1}}, + {{2, 1}}, + {{4, 1}}, + {{2, 1}, {4, -1}}, + {}, + {{7, 1}}, + {{5, -1}, {7, 1}}, + {{2, 1}, {4, 1}}, + {{6, 1}, {9, -1}}, + {{6, -1}}}; + ASSERT_ANY_THROW(Deijkstra(0, 9, graph)); } + +TEST(Deijkstra, Test_for_isolated_verticle) { + std::vector< std::vector< std::pair > > graph = {{{1, 1}, {8, 1}}, + {{2, 1}}, + {{4, 1}}, + {{2, 1}, {4, -1}}, + {}, + {{7, 1}}, + {{5, -1}, {7, 1}}, + {{2, 1}, {4, 1}}, + {{6, 1}, {9, -1}}, + {{6, -1}}, + {}, + {}}; + ASSERT_ANY_THROW(Deijkstra(0, 10, graph)); +} \ No newline at end of file diff --git a/task_05/src/RMQ.cpp b/task_05/src/RMQ.cpp new file mode 100644 index 0000000..ba981b7 --- /dev/null +++ b/task_05/src/RMQ.cpp @@ -0,0 +1,37 @@ +#include "RMQ.hpp" + +const int INF = 1e9; + +std::vector< std::vector > table_construct (int n, std::vector &vec) { + int new_size = ceil(log2(n)); + for (int i = n; i < pow(2, new_size); ++i) { + vec.push_back(INF); + } + int tmp = 1; + int count = 1; + std::vector< std::vector > vec2D; + vec2D.resize(pow(2, new_size)); + + std::vector tmp_vec = vec; + while(pow(2, tmp) <= pow(2, new_size)) { + for (int i = 0; i < tmp_vec.size() - count; ++i) { + vec2D[tmp].push_back(std::min(tmp_vec[i], tmp_vec[i + count])); + } + tmp_vec = vec2D[tmp]; + tmp++; + count *= 2; + } + + return vec2D; +} + +int RMQ (int a, int b, std::vector< std::vector > vec2D) { + if (a > b or a < 0 or b >= vec2D.size()) throw "Bad input"; + if (vec2D.size() == 0) throw "Empty array"; + int dist = b - a + 1; + int log_dist = floor(log2(dist)); + + int k = std::min (vec2D[log_dist][a], vec2D[log_dist][dist - pow(2, log_dist)]); + + return k; +} \ No newline at end of file diff --git a/task_05/src/RMQ.hpp b/task_05/src/RMQ.hpp new file mode 100644 index 0000000..5870774 --- /dev/null +++ b/task_05/src/RMQ.hpp @@ -0,0 +1,8 @@ +#pragma once +#include +#include +#include + +std::vector< std::vector > table_construct (int n, std::vector &vec); + +int RMQ (int a, int b, std::vector< std::vector > vec2D); \ No newline at end of file diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp index 0e4393b..e847218 100644 --- a/task_05/src/main.cpp +++ b/task_05/src/main.cpp @@ -1,3 +1,27 @@ #include +#include +#include +#include "RMQ.hpp" -int main() { return 0; } + + +int main () { + int n; + std::cin >> n; + + std::vector vec; + + int tmp; + + for( int i = 0; i < n; ++i ) { + std::cin >> tmp; + vec.push_back(tmp); + } + + std::vector< std::vector > vec2D = table_construct(n, vec); + + int a, b; + std::cin >> a >> b; + + int k = RMQ(a, b, vec2D); +} \ No newline at end of file diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index 5e11617..a33b7f1 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,6 +1,35 @@ #include +#include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +TEST(RMQ, Test1) { + std::vector vec = {1, 0, 4, 3, 5, 10}; + std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + ASSERT_EQ(RMQ(1, 7, vec2D), 0); } + +TEST(RMQ, Test2) { + std::vector vec = {14, 11, 13, 9, 7, 4, 10, 2, 5, 3}; + std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + ASSERT_EQ(RMQ(1, 8, vec2D), 2); +} + +TEST(RMQ, Test3) { + std::vector vec = {25, 16, 31, 50 ,5 ,21}; + std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + ASSERT_EQ(RMQ(4, 6, vec2D), 5); +} + + + +TEST(RMQ, Test_check_for_bad_input) { + std::vector vec = {14, 11, 13, 9, 7, 4, 10, 2, 5, 3}; + std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + ASSERT_ANY_THROW(RMQ(-1, 8, vec2D)); +} + +TEST(RMQ, Empty_vector) { + std::vector vec = {}; + std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + ASSERT_ANY_THROW(RMQ(1, 8, vec2D)); +} \ No newline at end of file From d1329071413b265e347d7ea53693e294310fe3ca Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Sat, 13 Jan 2024 16:59:47 +0000 Subject: [PATCH 3/8] task 1, 4, 5 --- doc/image.png | Bin 0 -> 144 bytes task_02/src/main.cpp | 6 +++++- task_03/src/main.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 doc/image.png diff --git a/doc/image.png b/doc/image.png new file mode 100644 index 0000000000000000000000000000000000000000..c04afbe0d2398fae98129c6f25111e8566da089a GIT binary patch literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^+(695!3HFgJ}hYlQsJI1jv*SN$q5b&jBIReGkJJ; zRu?9S&j?Zm^6mn8UIvUcCLW4`3N4L|j4ho^bAe(C--TFDb(CtKFqxq5DAmEX;DM5s nii29y9iB@L(@Yvu)Z`pcM?Bu6{1-oD!M +#include -int main() { return 0; } + +int main () { + +} \ No newline at end of file diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 0e4393b..503a47c 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,3 +1,45 @@ +#include #include -int main() { return 0; } + +const int INF = 1e9; + +class edge { +public: + int a; + int b; + int cost; +}; + +int main () { + int n = 5, m = 8; + + std::vector vec(n, INF); + std::vector edges = {{0, 1, -1}, {0, 2, 4}, + {1, 2, 3}, {1, 3, 2}, {1, 4, 2}, + {3, 2, 5}, {3, 1, 1}, + {4, 3, -3}}; + int v = 0; + vec[v] = 0; + std::vector p (n, -1); + int x; + for (int i = 0; i < n; ++i) { + x = -1; + for (int j = 0; j < m; ++j) { + if (vec[edges[j].a] < INF) { + if (vec[edges[j].b] > vec[edges[j].a] + edges[j].cost) { + vec[edges[j].b] = std::max (-INF, vec[edges[j].a] + edges[j].cost); + p[edges[j].b] = edges[j].a; + x = edges[j].b; + } + } + } + } + if (x != -1) { + throw "Negative Cycle"; + } + + for (auto i : vec) { + std::cout << i << " "; + } +} \ No newline at end of file From dda2ed5b5166562c2a04a236a2f2be84718099dc Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Sat, 13 Jan 2024 18:26:48 +0000 Subject: [PATCH 4/8] Fixed clang format 1, 4, 5 --- task_01/src/main.cpp | 31 ++++--- task_01/src/test.cpp | 34 ++------ task_01/src/topology_sort.cpp | 42 +++++----- task_01/src/topology_sort.hpp | 6 +- task_04/src/Deijkstra.cpp | 59 ++++++------- task_04/src/Deijkstra.hpp | 5 +- task_04/src/main.cpp | 38 +++++---- task_04/src/test.cpp | 151 ++++++++++++++++------------------ task_05/src/RMQ.cpp | 51 ++++++------ task_05/src/RMQ.hpp | 6 +- task_05/src/main.cpp | 31 ++++--- task_05/src/test.cpp | 15 ++-- 12 files changed, 221 insertions(+), 248 deletions(-) diff --git a/task_01/src/main.cpp b/task_01/src/main.cpp index a38f0cb..580abd3 100644 --- a/task_01/src/main.cpp +++ b/task_01/src/main.cpp @@ -1,24 +1,21 @@ +#include +#include #include #include -#include -#include -#include "topology_sort.hpp" +#include "topology_sort.hpp" +int main() { + int n, m; + std::cin >> n >> m; + std::vector > graph; + graph.resize(n); + int tmp_from, tmp_to; + for (int i = 0; i < m; ++i) { + std::cin >> tmp_from >> tmp_to; + graph[tmp_from].push_back(tmp_to); + } -int main () { - int n, m; - std::cin >> n >> m; - - std::vector< std::vector > graph; - graph.resize(n); - int tmp_from, tmp_to; - for (int i = 0; i < m; ++i) { - std::cin >> tmp_from >> tmp_to; - graph[tmp_from].push_back(tmp_to); - } - - std::vector vec = top_sort(graph); - + std::vector vec = top_sort(graph); } \ No newline at end of file diff --git a/task_01/src/test.cpp b/task_01/src/test.cpp index a40a732..8a3c282 100644 --- a/task_01/src/test.cpp +++ b/task_01/src/test.cpp @@ -4,53 +4,33 @@ #include "topology_sort.hpp" TEST(TopologySort, Simple) { - std::vector< std::vector > graph = {{2, 5, 4}, - {3, 5, 6}, - {}, - {2}, - {}, - {2, 3, 4}, - {3}, - {5}}; + std::vector> graph = {{2, 5, 4}, {3, 5, 6}, {}, {2}, + {}, {2, 3, 4}, {3}, {5}}; std::vector ans = {7, 1, 6, 0, 5, 4, 3, 2}; ASSERT_EQ(top_sort(graph), ans); } - TEST(TopologySort, Cycle) { - std::vector< std::vector > graph = {{1}, - {2}, - {0, 1, 2}, - {}}; + std::vector> graph = {{1}, {2}, {0, 1, 2}, {}}; std::vector ans = {3, 0, 1, 2}; ASSERT_EQ(top_sort(graph), ans); } TEST(TopologySort, Empty_graph) { - std::vector< std::vector > graph = {{0}}; + std::vector> graph = {{0}}; std::vector ans = {0}; ASSERT_EQ(top_sort(graph), ans); } TEST(TopologySort, Full_graph_with_loops) { - std::vector< std::vector > graph = {{0, 1, 2}, - {0, 1, 2}, - {0, 1, 2}}; + std::vector> graph = {{0, 1, 2}, {0, 1, 2}, {0, 1, 2}}; std::vector ans = {0, 1, 2}; ASSERT_EQ(top_sort(graph), ans); } TEST(TopologySort, BIK_graph) { - std::vector< std::vector > graph = {{1, 2, 3}, - {5}, - {5}, - {4, 5}, - {6, 8}, - {4, 6, 7}, - {9}, - {9}, - {7, 9}, - {}}; + std::vector> graph = {{1, 2, 3}, {5}, {5}, {4, 5}, {6, 8}, + {4, 6, 7}, {9}, {9}, {7, 9}, {}}; std::vector ans = {0, 3, 2, 1, 5, 4, 8, 7, 6, 9}; ASSERT_EQ(top_sort(graph), ans); } diff --git a/task_01/src/topology_sort.cpp b/task_01/src/topology_sort.cpp index 84eb0ff..578972c 100644 --- a/task_01/src/topology_sort.cpp +++ b/task_01/src/topology_sort.cpp @@ -1,28 +1,28 @@ #include "topology_sort.hpp" + #include -void dfs (int v, std::vector &used, std::vector &result, std::vector< std::vector > &graph) { - used[v] = true; - for (int i = 0; i < graph[v].size(); ++i) { - int to = graph[v][i]; - if(!used[to]) - dfs(to, used, result, graph); - } - - result.push_back(v); +void dfs(int v, std::vector &used, std::vector &result, + std::vector > &graph) { + used[v] = true; + for (int i = 0; i < graph[v].size(); ++i) { + int to = graph[v][i]; + if (!used[to]) dfs(to, used, result, graph); + } + + result.push_back(v); } -std::vector top_sort (std::vector< std::vector > &graph) { - std::vector used; - used.resize(graph.size()); - - std::vector result; - for (int i = 0; i < graph.size(); ++i) { - if (!used[i]) - dfs(i, used, result, graph); - } - - reverse(result.begin(), result.end()); +std::vector top_sort(std::vector > &graph) { + std::vector used; + used.resize(graph.size()); + + std::vector result; + for (int i = 0; i < graph.size(); ++i) { + if (!used[i]) dfs(i, used, result, graph); + } + + reverse(result.begin(), result.end()); - return result; + return result; } \ No newline at end of file diff --git a/task_01/src/topology_sort.hpp b/task_01/src/topology_sort.hpp index b37e586..1d0c09f 100644 --- a/task_01/src/topology_sort.hpp +++ b/task_01/src/topology_sort.hpp @@ -1,7 +1,7 @@ #pragma once #include +void dfs(int v, std::vector &used, std::vector &result, + std::vector > &graph); -void dfs (int v, std::vector &used, std::vector &result, std::vector< std::vector > &graph); - -std::vector top_sort (std::vector< std::vector > &graph); \ No newline at end of file +std::vector top_sort(std::vector > &graph); \ No newline at end of file diff --git a/task_04/src/Deijkstra.cpp b/task_04/src/Deijkstra.cpp index f7fc999..38a76fa 100644 --- a/task_04/src/Deijkstra.cpp +++ b/task_04/src/Deijkstra.cpp @@ -1,35 +1,38 @@ #include "Deijkstra.hpp" + #include const int INF = 1e9; -int Deijkstra(int start, int end, std::vector< std::vector< std::pair > > &graph) { - - if (end >= graph.size() or start < 0) { throw "Bad Input"; } - - if (graph.size() == 0) throw "Empty Graph"; - - std::vector dist(graph.size(), INF); - dist[start] = 0; - std::vector used(graph.size()); - - for(int i = 0; i < graph.size(); ++i) { - int closest = -1; - for(int j = 0; j < graph.size(); ++j) { - if (!used[j] && (closest == -1 || dist[closest] > dist[j])) { - closest = j; - } - } - - used[closest] = true; - - for(auto &[to, weight] : graph[closest]) { - if (weight < 0) throw "Negative Weight!"; - if (dist[to] > dist[closest] + weight) { - dist[to] = dist[closest] + weight; - } - } +int Deijkstra(int start, int end, + std::vector > > &graph) { + if (end >= graph.size() or start < 0) { + throw "Bad Input"; + } + + if (graph.size() == 0) throw "Empty Graph"; + + std::vector dist(graph.size(), INF); + dist[start] = 0; + std::vector used(graph.size()); + + for (int i = 0; i < graph.size(); ++i) { + int closest = -1; + for (int j = 0; j < graph.size(); ++j) { + if (!used[j] && (closest == -1 || dist[closest] > dist[j])) { + closest = j; + } + } + + used[closest] = true; + + for (auto &[to, weight] : graph[closest]) { + if (weight < 0) throw "Negative Weight!"; + if (dist[to] > dist[closest] + weight) { + dist[to] = dist[closest] + weight; + } } - if (dist[end] == INF) throw "No path to this verticle!"; - return dist[end]; + } + if (dist[end] == INF) throw "No path to this verticle!"; + return dist[end]; } \ No newline at end of file diff --git a/task_04/src/Deijkstra.hpp b/task_04/src/Deijkstra.hpp index 683da2a..6c0fff4 100644 --- a/task_04/src/Deijkstra.hpp +++ b/task_04/src/Deijkstra.hpp @@ -1,4 +1,5 @@ -#pragma once +#pragma once #include -int Deijkstra(int start, int end, std::vector< std::vector< std::pair > > &graph); \ No newline at end of file +int Deijkstra(int start, int end, + std::vector > > &graph); \ No newline at end of file diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index bbcacdf..6c6d1b9 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -1,25 +1,27 @@ #include #include + #include "Deijkstra.hpp" using namespace std; -int main () { - int n, m; - cin >> n >> m; - - vector< vector< pair > > graph; - graph.resize(n); - - int from, to, weight; - - for(int i = 0; i < m; ++i) { - cin >> from >> to >> weight; - graph[from].push_back( {to, weight} ); - } - - int start, end; cin >> start >> end; - int k = Deijkstra(start, end, graph); - - cout << k; +int main() { + int n, m; + cin >> n >> m; + + vector > > graph; + graph.resize(n); + + int from, to, weight; + + for (int i = 0; i < m; ++i) { + cin >> from >> to >> weight; + graph[from].push_back({to, weight}); + } + + int start, end; + cin >> start >> end; + int k = Deijkstra(start, end, graph); + + cout << k; } \ No newline at end of file diff --git a/task_04/src/test.cpp b/task_04/src/test.cpp index 0588df6..627afa9 100644 --- a/task_04/src/test.cpp +++ b/task_04/src/test.cpp @@ -1,118 +1,109 @@ #include + #include "Deijkstra.hpp" TEST(Deijkstra, Test_default_graph_1) { - std::vector< std::vector< std::pair > > graph = {{{1, 1}, {8, 1}}, - {{2, 1}}, - {{4, 1}}, - {{2, 1}, {4, 1}}, - {}, - {{7, 1}}, - {{5, 1}, {7, 1}}, - {{2, 1}, {4, 1}}, - {{6, 1}, {9, 1}}, - {{6, 1}}}; + std::vector > > graph = {{{1, 1}, {8, 1}}, + {{2, 1}}, + {{4, 1}}, + {{2, 1}, {4, 1}}, + {}, + {{7, 1}}, + {{5, 1}, {7, 1}}, + {{2, 1}, {4, 1}}, + {{6, 1}, {9, 1}}, + {{6, 1}}}; ASSERT_EQ(Deijkstra(0, 4, graph), 3); } TEST(Deijkstra, Test_default_graph_2) { - std::vector< std::vector< std::pair > > graph = {{{1, 10}, {2, 7}}, - {{4, 3}, {3, 9}}, - {{3, 11}, {5, 2}}, - {{6, 8}, {7, 12}, {8, 1}}, - {{6, 4}}, - {{8, 5}}, - {{9, 6}}, - {{9, 13}}, - {{9, 8}}, - {}}; + std::vector > > graph = { + {{1, 10}, {2, 7}}, {{4, 3}, {3, 9}}, + {{3, 11}, {5, 2}}, {{6, 8}, {7, 12}, {8, 1}}, + {{6, 4}}, {{8, 5}}, + {{9, 6}}, {{9, 13}}, + {{9, 8}}, {}}; ASSERT_EQ(Deijkstra(0, 9, graph), 22); } TEST(Deijkstra, Test_default_graph_3) { - std::vector< std::vector< std::pair > > graph = {{{1, 2}, {2, 2}, {5, 3}}, - {{2, 1}, {3, 2}, {6, 8}}, - {{3, 1}, {5, 4}}, - {{6, 3}, {4, 2}}, - {{5, 4}, {7, 6}}, - {{7, 7}}, - {{7, 8}}, - {}}; + std::vector > > graph = { + {{1, 2}, {2, 2}, {5, 3}}, + {{2, 1}, {3, 2}, {6, 8}}, + {{3, 1}, {5, 4}}, + {{6, 3}, {4, 2}}, + {{5, 4}, {7, 6}}, + {{7, 7}}, + {{7, 8}}, + {}}; ASSERT_EQ(Deijkstra(0, 7, graph), 10); } TEST(Deijkstra, Test_default_graph_4) { - std::vector< std::vector< std::pair > > graph = {{{1, 10}, {3, 8}, {4, 31}}, - {{2, 7}}, - {{3, 9}, {7, 27}}, - {{5, 11}}, - {{6, 32}}, - {{6, 17}, {8, 15}}, - {{8, 21}}, - {{8, 15}}, - {}}; + std::vector > > graph = { + {{1, 10}, {3, 8}, {4, 31}}, + {{2, 7}}, + {{3, 9}, {7, 27}}, + {{5, 11}}, + {{6, 32}}, + {{6, 17}, {8, 15}}, + {{8, 21}}, + {{8, 15}}, + {}}; ASSERT_EQ(Deijkstra(0, 3, graph), 8); } TEST(Deijkstra, Test_check_for_bad_input_1) { - std::vector< std::vector< std::pair > > graph = {{{1, 10}, {2, 7}}, - {{4, 3}, {3, 9}}, - {{3, 11}, {5, 2}}, - {{6, 8}, {7, 12}, {8, 1}}, - {{6, 4}}, - {{8, 5}}, - {{9, 6}}, - {{9, 13}}, - {{9, 8}}, - {}}; + std::vector > > graph = { + {{1, 10}, {2, 7}}, {{4, 3}, {3, 9}}, + {{3, 11}, {5, 2}}, {{6, 8}, {7, 12}, {8, 1}}, + {{6, 4}}, {{8, 5}}, + {{9, 6}}, {{9, 13}}, + {{9, 8}}, {}}; ASSERT_ANY_THROW(Deijkstra(0, 10, graph)); } TEST(Deijkstra, Test_check_for_bad_input_2) { - std::vector< std::vector< std::pair > > graph = {{{1, 10}, {2, 7}}, - {{4, 3}, {3, 9}}, - {{3, 11}, {5, 2}}, - {{6, 8}, {7, 12}, {8, 1}}, - {{6, 4}}, - {{8, 5}}, - {{9, 6}}, - {{9, 13}}, - {{9, 8}}, - {}}; + std::vector > > graph = { + {{1, 10}, {2, 7}}, {{4, 3}, {3, 9}}, + {{3, 11}, {5, 2}}, {{6, 8}, {7, 12}, {8, 1}}, + {{6, 4}}, {{8, 5}}, + {{9, 6}}, {{9, 13}}, + {{9, 8}}, {}}; ASSERT_ANY_THROW(Deijkstra(-6, 9, graph)); } TEST(Deijkstra, Test_empty_graph) { - std::vector< std::vector< std::pair > > graph = {}; + std::vector > > graph = {}; ASSERT_ANY_THROW(Deijkstra(0, 9, graph)); } TEST(Deijkstra, Test_default_graph_with_negative_weights) { - std::vector< std::vector< std::pair > > graph = {{{1, 1}, {8, 1}}, - {{2, 1}}, - {{4, 1}}, - {{2, 1}, {4, -1}}, - {}, - {{7, 1}}, - {{5, -1}, {7, 1}}, - {{2, 1}, {4, 1}}, - {{6, 1}, {9, -1}}, - {{6, -1}}}; + std::vector > > graph = {{{1, 1}, {8, 1}}, + {{2, 1}}, + {{4, 1}}, + {{2, 1}, {4, -1}}, + {}, + {{7, 1}}, + {{5, -1}, {7, 1}}, + {{2, 1}, {4, 1}}, + {{6, 1}, {9, -1}}, + {{6, -1}}}; ASSERT_ANY_THROW(Deijkstra(0, 9, graph)); } TEST(Deijkstra, Test_for_isolated_verticle) { - std::vector< std::vector< std::pair > > graph = {{{1, 1}, {8, 1}}, - {{2, 1}}, - {{4, 1}}, - {{2, 1}, {4, -1}}, - {}, - {{7, 1}}, - {{5, -1}, {7, 1}}, - {{2, 1}, {4, 1}}, - {{6, 1}, {9, -1}}, - {{6, -1}}, - {}, - {}}; + std::vector > > graph = {{{1, 1}, {8, 1}}, + {{2, 1}}, + {{4, 1}}, + {{2, 1}, {4, -1}}, + {}, + {{7, 1}}, + {{5, -1}, {7, 1}}, + {{2, 1}, {4, 1}}, + {{6, 1}, {9, -1}}, + {{6, -1}}, + {}, + {}}; ASSERT_ANY_THROW(Deijkstra(0, 10, graph)); } \ No newline at end of file diff --git a/task_05/src/RMQ.cpp b/task_05/src/RMQ.cpp index ba981b7..57ffbb0 100644 --- a/task_05/src/RMQ.cpp +++ b/task_05/src/RMQ.cpp @@ -2,36 +2,37 @@ const int INF = 1e9; -std::vector< std::vector > table_construct (int n, std::vector &vec) { - int new_size = ceil(log2(n)); - for (int i = n; i < pow(2, new_size); ++i) { - vec.push_back(INF); - } - int tmp = 1; - int count = 1; - std::vector< std::vector > vec2D; - vec2D.resize(pow(2, new_size)); +std::vector > table_construct(int n, std::vector &vec) { + int new_size = ceil(log2(n)); + for (int i = n; i < pow(2, new_size); ++i) { + vec.push_back(INF); + } + int tmp = 1; + int count = 1; + std::vector > vec2D; + vec2D.resize(pow(2, new_size)); - std::vector tmp_vec = vec; - while(pow(2, tmp) <= pow(2, new_size)) { - for (int i = 0; i < tmp_vec.size() - count; ++i) { - vec2D[tmp].push_back(std::min(tmp_vec[i], tmp_vec[i + count])); - } - tmp_vec = vec2D[tmp]; - tmp++; - count *= 2; + std::vector tmp_vec = vec; + while (pow(2, tmp) <= pow(2, new_size)) { + for (int i = 0; i < tmp_vec.size() - count; ++i) { + vec2D[tmp].push_back(std::min(tmp_vec[i], tmp_vec[i + count])); } + tmp_vec = vec2D[tmp]; + tmp++; + count *= 2; + } - return vec2D; + return vec2D; } -int RMQ (int a, int b, std::vector< std::vector > vec2D) { - if (a > b or a < 0 or b >= vec2D.size()) throw "Bad input"; - if (vec2D.size() == 0) throw "Empty array"; - int dist = b - a + 1; - int log_dist = floor(log2(dist)); +int RMQ(int a, int b, std::vector > vec2D) { + if (a > b or a < 0 or b >= vec2D.size()) throw "Bad input"; + if (vec2D.size() == 0) throw "Empty array"; + int dist = b - a + 1; + int log_dist = floor(log2(dist)); - int k = std::min (vec2D[log_dist][a], vec2D[log_dist][dist - pow(2, log_dist)]); + int k = + std::min(vec2D[log_dist][a], vec2D[log_dist][dist - pow(2, log_dist)]); - return k; + return k; } \ No newline at end of file diff --git a/task_05/src/RMQ.hpp b/task_05/src/RMQ.hpp index 5870774..5ded0b9 100644 --- a/task_05/src/RMQ.hpp +++ b/task_05/src/RMQ.hpp @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include -std::vector< std::vector > table_construct (int n, std::vector &vec); +std::vector > table_construct(int n, std::vector &vec); -int RMQ (int a, int b, std::vector< std::vector > vec2D); \ No newline at end of file +int RMQ(int a, int b, std::vector > vec2D); \ No newline at end of file diff --git a/task_05/src/main.cpp b/task_05/src/main.cpp index e847218..aff3954 100644 --- a/task_05/src/main.cpp +++ b/task_05/src/main.cpp @@ -1,27 +1,26 @@ +#include #include #include -#include -#include "RMQ.hpp" +#include "RMQ.hpp" +int main() { + int n; + std::cin >> n; -int main () { - int n; - std::cin >> n; + std::vector vec; - std::vector vec; + int tmp; - int tmp; + for (int i = 0; i < n; ++i) { + std::cin >> tmp; + vec.push_back(tmp); + } - for( int i = 0; i < n; ++i ) { - std::cin >> tmp; - vec.push_back(tmp); - } - - std::vector< std::vector > vec2D = table_construct(n, vec); + std::vector > vec2D = table_construct(n, vec); - int a, b; - std::cin >> a >> b; + int a, b; + std::cin >> a >> b; - int k = RMQ(a, b, vec2D); + int k = RMQ(a, b, vec2D); } \ No newline at end of file diff --git a/task_05/src/test.cpp b/task_05/src/test.cpp index a33b7f1..0421bf8 100644 --- a/task_05/src/test.cpp +++ b/task_05/src/test.cpp @@ -1,35 +1,34 @@ #include + #include TEST(RMQ, Test1) { std::vector vec = {1, 0, 4, 3, 5, 10}; - std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + std::vector > vec2D = table_construct(vec.size(), vec); ASSERT_EQ(RMQ(1, 7, vec2D), 0); } TEST(RMQ, Test2) { std::vector vec = {14, 11, 13, 9, 7, 4, 10, 2, 5, 3}; - std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + std::vector > vec2D = table_construct(vec.size(), vec); ASSERT_EQ(RMQ(1, 8, vec2D), 2); } TEST(RMQ, Test3) { - std::vector vec = {25, 16, 31, 50 ,5 ,21}; - std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + std::vector vec = {25, 16, 31, 50, 5, 21}; + std::vector > vec2D = table_construct(vec.size(), vec); ASSERT_EQ(RMQ(4, 6, vec2D), 5); } - - TEST(RMQ, Test_check_for_bad_input) { std::vector vec = {14, 11, 13, 9, 7, 4, 10, 2, 5, 3}; - std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + std::vector > vec2D = table_construct(vec.size(), vec); ASSERT_ANY_THROW(RMQ(-1, 8, vec2D)); } TEST(RMQ, Empty_vector) { std::vector vec = {}; - std::vector< std::vector > vec2D = table_construct(vec.size(), vec); + std::vector > vec2D = table_construct(vec.size(), vec); ASSERT_ANY_THROW(RMQ(1, 8, vec2D)); } \ No newline at end of file From 29f52fc4b5679723fdbbfa2543976912796b0766 Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Sat, 13 Jan 2024 18:29:41 +0000 Subject: [PATCH 5/8] Nothing in 2, 3 yet --- task_02/src/main.cpp | 5 +--- task_03/src/main.cpp | 67 +++++++++++++++++++++----------------------- 2 files changed, 33 insertions(+), 39 deletions(-) diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp index 2982306..5040d02 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,7 +1,4 @@ #include #include - -int main () { - -} \ No newline at end of file +int main() {} \ No newline at end of file diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 503a47c..46a12b3 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,45 +1,42 @@ -#include #include - +#include const int INF = 1e9; class edge { -public: - int a; - int b; - int cost; + public: + int a; + int b; + int cost; }; -int main () { - int n = 5, m = 8; - - std::vector vec(n, INF); - std::vector edges = {{0, 1, -1}, {0, 2, 4}, - {1, 2, 3}, {1, 3, 2}, {1, 4, 2}, - {3, 2, 5}, {3, 1, 1}, - {4, 3, -3}}; - int v = 0; - vec[v] = 0; - std::vector p (n, -1); - int x; - for (int i = 0; i < n; ++i) { - x = -1; - for (int j = 0; j < m; ++j) { - if (vec[edges[j].a] < INF) { - if (vec[edges[j].b] > vec[edges[j].a] + edges[j].cost) { - vec[edges[j].b] = std::max (-INF, vec[edges[j].a] + edges[j].cost); - p[edges[j].b] = edges[j].a; - x = edges[j].b; - } - } +int main() { + int n = 5, m = 8; + + std::vector vec(n, INF); + std::vector edges = {{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, {1, 3, 2}, + {1, 4, 2}, {3, 2, 5}, {3, 1, 1}, {4, 3, -3}}; + int v = 0; + vec[v] = 0; + std::vector p(n, -1); + int x; + for (int i = 0; i < n; ++i) { + x = -1; + for (int j = 0; j < m; ++j) { + if (vec[edges[j].a] < INF) { + if (vec[edges[j].b] > vec[edges[j].a] + edges[j].cost) { + vec[edges[j].b] = std::max(-INF, vec[edges[j].a] + edges[j].cost); + p[edges[j].b] = edges[j].a; + x = edges[j].b; } + } } - if (x != -1) { - throw "Negative Cycle"; - } - - for (auto i : vec) { - std::cout << i << " "; - } + } + if (x != -1) { + throw "Negative Cycle"; + } + + for (auto i : vec) { + std::cout << i << " "; + } } \ No newline at end of file From 53a5e3e874467900dba32167673e48c8ed3f6145 Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Sun, 14 Jan 2024 20:19:53 +0000 Subject: [PATCH 6/8] Added 2, 6 with tests --- task_02/src/AllFunc.cpp | 25 ++++++++++++ task_02/src/AllFunc.hpp | 7 ++++ task_02/src/FindBridges.cpp | 27 ++++++++++++ task_02/src/FindBridges.hpp | 14 +++++++ task_02/src/FindCutPoints.cpp | 26 ++++++++++++ task_02/src/FindCutPoints.hpp | 12 ++++++ task_02/src/main.cpp | 4 +- task_02/src/test.cpp | 70 ++++++++++++++++++++++++++++++- task_06/src/LCA.cpp | 77 +++++++++++++++++++++++++++++++++++ task_06/src/LCA.hpp | 17 ++++++++ task_06/src/main.cpp | 24 ++++++++++- task_06/src/test.cpp | 40 +++++++++++++++++- 12 files changed, 335 insertions(+), 8 deletions(-) create mode 100644 task_02/src/AllFunc.cpp create mode 100644 task_02/src/AllFunc.hpp create mode 100644 task_02/src/FindBridges.cpp create mode 100644 task_02/src/FindBridges.hpp create mode 100644 task_02/src/FindCutPoints.cpp create mode 100644 task_02/src/FindCutPoints.hpp create mode 100644 task_06/src/LCA.cpp create mode 100644 task_06/src/LCA.hpp diff --git a/task_02/src/AllFunc.cpp b/task_02/src/AllFunc.cpp new file mode 100644 index 0000000..299840c --- /dev/null +++ b/task_02/src/AllFunc.cpp @@ -0,0 +1,25 @@ +#include "AllFunc.hpp" + +void AllFunc(std::vector > &graph, + std::set > &result, std::set &cpvector) { + int timer = 0, parent = -1; + + std::vector tin(graph.size(), 0); + std::vector fup(graph.size(), 0); + std::vector used(graph.size(), 0); + + std::set > res; + + std::set cpvec; + + for (int i = 0; i < graph.size(); i++) { + if (!used[i]) { + FindBridges(timer, i, graph, tin, fup, parent, res, used); + } + } + result = returnBridges(res); + tin.resize(graph.size(), 0); + fup.resize(graph.size(), 0); + used.resize(graph.size(), 0); + FindCutPoint(timer, 0, graph, tin, fup, parent, cpvec, used); +} \ No newline at end of file diff --git a/task_02/src/AllFunc.hpp b/task_02/src/AllFunc.hpp new file mode 100644 index 0000000..4ef9f19 --- /dev/null +++ b/task_02/src/AllFunc.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include "FindBridges.hpp" +#include "FindCutPoints.hpp" + +void AllFunc(std::vector > &graph, + std::set > &result, std::set &cpvector); \ No newline at end of file diff --git a/task_02/src/FindBridges.cpp b/task_02/src/FindBridges.cpp new file mode 100644 index 0000000..116a18a --- /dev/null +++ b/task_02/src/FindBridges.cpp @@ -0,0 +1,27 @@ +#include "FindBridges.hpp" + +void FindBridges(int &timer, int start, std::vector > &graph, + std::vector &tin, std::vector &fup, int parent, + std::set > &result, + std::vector used) { + used[start] = 1; + tin[start] = fup[start] = ++timer; + int to; + for (int i = 0; i < graph[start].size(); ++i) { + to = graph[start][i]; + if (to == parent) continue; + if (used[to]) + fup[start] = std::min(fup[start], tin[to]); + else { + FindBridges(timer, to, graph, tin, fup, start, result, used); + fup[start] = std::min(fup[start], fup[to]); + if (fup[to] > tin[start]) + result.insert({std::min(start, to), std::max(start, to)}); + } + } +} + +std::set > returnBridges( + std::set > &result) { + return result; +} \ No newline at end of file diff --git a/task_02/src/FindBridges.hpp b/task_02/src/FindBridges.hpp new file mode 100644 index 0000000..09ce986 --- /dev/null +++ b/task_02/src/FindBridges.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include +#include + +void FindBridges(int &timer, int start, std::vector > &graph, + std::vector &tin, std::vector &fup, int parent, + std::set > &result, + std::vector used); + +std::set > returnBridges( + std::set > &result); \ No newline at end of file diff --git a/task_02/src/FindCutPoints.cpp b/task_02/src/FindCutPoints.cpp new file mode 100644 index 0000000..7d3ad18 --- /dev/null +++ b/task_02/src/FindCutPoints.cpp @@ -0,0 +1,26 @@ +#include "FindCutPoints.hpp" + +void FindCutPoint (int &timer, int start, std::vector< std::vector > &graph, std::vector &tin, std::vector &fup, int parent, std::set &cpvec, std::vector used) { + used[start] = 1; + tin[start] = fup[start] = ++timer; + int to; + int children = 0; + for (int i = 0; i < graph[start].size(); ++i) { + to = graph[start][i]; + if (to == parent) continue; + if (used[to]) + fup[start] = std::min(fup[start], tin[to]); + else { + FindCutPoint(timer, to, graph, tin, fup, start, cpvec, used); + fup[start] = std::min(fup[start], fup[to]); + if (fup[to] >= tin[start] && parent != -1) + cpvec.insert(start); + children++; + } + } + +} + +std::set returnCP (std::set &cpvec) { + return cpvec; +} \ No newline at end of file diff --git a/task_02/src/FindCutPoints.hpp b/task_02/src/FindCutPoints.hpp new file mode 100644 index 0000000..b958c51 --- /dev/null +++ b/task_02/src/FindCutPoints.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include +#include + +void FindCutPoint(int &timer, int start, std::vector > &graph, + std::vector &tin, std::vector &fup, int parent, + std::set &cpvec, std::vector used); + +std::set returnCP(std::set &cpvec); \ No newline at end of file diff --git a/task_02/src/main.cpp b/task_02/src/main.cpp index 5040d02..7159b03 100644 --- a/task_02/src/main.cpp +++ b/task_02/src/main.cpp @@ -1,4 +1,4 @@ -#include -#include +#include "FindBridges.hpp" +#include "FindCutPoints.hpp" int main() {} \ No newline at end of file diff --git a/task_02/src/test.cpp b/task_02/src/test.cpp index 5e11617..8921c21 100644 --- a/task_02/src/test.cpp +++ b/task_02/src/test.cpp @@ -1,6 +1,72 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "AllFunc.hpp" +#include "FindBridges.hpp" +#include "FindCutPoints.hpp" + +TEST(Bridges_and_CutPoints, Simple_Bridges) { + std::vector > graph = {{0, 1}, {1, 0}}; + std::set > result; + std::set cpvector; + AllFunc(graph, result, cpvector); + std::set > k = {{0, 1}}; + ASSERT_EQ(returnBridges(result), k); +} + +TEST(Bridges_and_CutPoints, Simple_CutPoints) { + std::vector > graph = {{0, 1}, {1, 0}}; + std::set > result; + std::set cpvector; + AllFunc(graph, result, cpvector); + std::set k = {}; + ASSERT_EQ(returnCP(cpvector), k); +} + +TEST(Bridges_and_CutPoints, Harder_Bridges) { + std::vector > graph = {{1, 2}, {0, 2, 3}, {0, 1}, + {1, 4, 5}, {3, 5}, {3, 4}}; + std::set > result; + std::set cpvector; + AllFunc(graph, result, cpvector); + std::set > k = {{1, 3}}; + ASSERT_EQ(returnBridges(result), k); +} + +TEST(Bridges_and_CutPoints, Harder_CutPoints_ale) { + std::vector > graph = {{1, 2}, {0, 2, 3}, {0, 1}, + {1, 4, 5}, {3, 5}, {3, 4}}; + std::vector tin(graph.size()); + std::vector fup(graph.size()); + std::vector used(graph.size()); + int tm = 0; + std::set > result; + std::set cpvector; + FindCutPoint(tm, 0, graph, tin, fup, -1, cpvector, used); + std::set k = {1, 3}; + ASSERT_EQ(returnCP(cpvector), k); +} + +TEST(Bridges_and_CutPoints, Most_hard_Bridges) { + std::vector > graph = { + {1, 3}, {0, 2, 3}, {1, 3}, {0, 1, 2, 4, 5, 6}, {3, 5}, {3, 4, 6}, {3, 5}}; + std::set > result; + std::set cpvector; + AllFunc(graph, result, cpvector); + std::set > k = {}; + ASSERT_EQ(returnBridges(result), k); +} + +TEST(Bridges_and_CutPoints, Most_hard_CutPoints) { + std::vector > graph = { + {1, 3}, {0, 2, 3}, {1, 3}, {0, 1, 2, 4, 5, 6}, {3, 5}, {3, 4, 6}, {3, 5}}; + std::vector tin(graph.size()); + std::vector fup(graph.size()); + std::vector used(graph.size()); + int tm = 0; + std::set > result; + std::set cpvector; + FindCutPoint(tm, 0, graph, tin, fup, -1, cpvector, used); + std::set k = {3}; + ASSERT_EQ(returnCP(cpvector), k); } diff --git a/task_06/src/LCA.cpp b/task_06/src/LCA.cpp new file mode 100644 index 0000000..6202da8 --- /dev/null +++ b/task_06/src/LCA.cpp @@ -0,0 +1,77 @@ +#include "LCA.hpp" + +std::vector lca_h, lca_dfs_list, lca_first, lca_tree; +std::vector lca_dfs_used; + +bool Empty = false; +bool OnlyRoot = false; + +void lca_dfs(const graph &graph, int v, int h) { + lca_dfs_used[v] = 1; + lca_h[v] = h; + lca_dfs_list.push_back(v); + for (const_graph_iter i = graph[v].begin(); i != graph[v].end(); ++i) { + if (!lca_dfs_used[*i]) { + lca_dfs(graph, *i, h + 1); + lca_dfs_list.push_back(v); + } + } +} + +void lca_build_tree(int i, int l, int r) { + if (l == r) + lca_tree[i] = lca_dfs_list[l]; + else { + int m = (l + r) >> 1; + lca_build_tree(i + i, l, m); + lca_build_tree(i + i + 1, m + 1, r); + if (lca_h[lca_tree[i + i]] < lca_h[lca_tree[i + i + 1]]) + lca_tree[i] = lca_tree[i + i]; + else + lca_tree[i] = lca_tree[i + i + 1]; + } +} + +void lca_prepare(const graph &graph, int root) { + if (graph.empty()) { + Empty = true; + } else { + if (graph.size() == 1) { + OnlyRoot = true; + } else { + int n = (int)graph.size(); + lca_h.resize(n); + lca_dfs_list.reserve(n * 2); + lca_dfs_used.assign(n, 0); + + lca_dfs(graph, root); + + int m = (int)lca_dfs_list.size(); + lca_tree.assign(lca_dfs_list.size() * 4 + 1, -1); + lca_build_tree(1, 0, m - 1); + + lca_first.assign(n, -1); + for (int i = 0; i <= m; ++i) { + int v = lca_dfs_list[i]; + if (lca_first[v] == -1) lca_first[v] = i; + } + } + } +} + +int lca_tree_min(int i, int sl, int sr, int l, int r) { + if (sl == l && sr == r) return lca_tree[i]; + int sm = (sl + sr) >> 1; + if (r <= sm) return lca_tree_min(i + i, sl, sm, l, r); + if (l > sm) return lca_tree_min(i + i + 1, sm + 1, sr, l, r); + int ans1 = lca_tree_min(i + i, sl, sm, l, sm); + int ans2 = lca_tree_min(i + i + 1, sm + 1, sr, sm + 1, r); + return lca_h[ans1] < lca_h[ans2] ? ans1 : ans2; +} + +int lca(int a, int b) { + if (Empty or OnlyRoot) throw "Error"; + int left = lca_first[a], right = lca_first[b]; + if (left > right) std::swap(left, right); + return lca_tree_min(1, 0, (int)lca_dfs_list.size() - 1, left, right); +} \ No newline at end of file diff --git a/task_06/src/LCA.hpp b/task_06/src/LCA.hpp new file mode 100644 index 0000000..3391406 --- /dev/null +++ b/task_06/src/LCA.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +typedef std::vector> graph; +typedef std::vector::const_iterator const_graph_iter; + +void lca_dfs(const graph &graph, int v, int h = 1); + +void lca_build_tree(int i, int l, int r); + +void lca_prepare(const graph &graph, int root); + +int lca_tree_min(int i, int sl, int sr, int l, int r); + +int lca(int a, int b); \ No newline at end of file diff --git a/task_06/src/main.cpp b/task_06/src/main.cpp index 0e4393b..bc147b2 100644 --- a/task_06/src/main.cpp +++ b/task_06/src/main.cpp @@ -1,3 +1,23 @@ -#include +#include "LCA.hpp" -int main() { return 0; } +int main() { + int n, m, root; + std::cin >> n >> m; + + graph g; + g.resize(n); + + int from, to; + + for (int i = 0; i < m; ++i) { + std::cin >> from >> to; + g[from].push_back(to); + g[to].push_back(from); + } + std::cin >> root; + lca_prepare(g, root); + + int v1, v2; + std::cin >> v1 >> v2; + std::cout << lca(v1, v2); +} \ No newline at end of file diff --git a/task_06/src/test.cpp b/task_06/src/test.cpp index 5e11617..68b8e43 100644 --- a/task_06/src/test.cpp +++ b/task_06/src/test.cpp @@ -1,6 +1,42 @@ #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "LCA.hpp" + +TEST(LCA, Simple) { + graph g = {{1, 2}, {0}, {0}}; + lca_prepare(g, 0); + ASSERT_EQ(lca(1, 2), 0); +} + +TEST(LCA, Difiicult) { + graph g = {{1, 2}, {0, 3, 4}, {0, 5}, {1}, {1, 6, 7}, {2, 8}, {4}, {4}, {5}}; + lca_prepare(g, 0); + ASSERT_EQ(lca(3, 7), 1); +} + +TEST(LCA, Difiicult_2) { + graph g = {{1, 2}, {0, 3, 4}, {0, 5}, {1}, {1, 6, 7}, {2, 8}, {4}, {4}, {5}}; + lca_prepare(g, 0); + ASSERT_EQ(lca(1, 8), 0); } + +TEST(LCA, Hard) { + graph g = {{1, 14}, {0, 2, 3}, {1, 4, 5}, {1, 6, 7}, {2}, + {2}, {3, 9, 8}, {3, 10, 13}, {6}, {6}, + {7, 11, 12}, {10}, {10}, {7}, {1}}; + lca_prepare(g, 0); + ASSERT_EQ(lca(9, 13), 3); +} + +TEST(LCA, Empty) { + graph g = {}; + lca_prepare(g, 0); + ASSERT_ANY_THROW(lca(1, 4)); +} + +TEST(LCA, Only_Root) { + graph g = {{}}; + lca_prepare(g, 0); + ASSERT_ANY_THROW(lca(1, 4)); +} \ No newline at end of file From e9188628678d746053a6821b68765ba77021e772 Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Sun, 14 Jan 2024 20:23:43 +0000 Subject: [PATCH 7/8] Fixed clang in 2 task --- task_02/src/FindCutPoints.cpp | 40 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/task_02/src/FindCutPoints.cpp b/task_02/src/FindCutPoints.cpp index 7d3ad18..1fbaa2d 100644 --- a/task_02/src/FindCutPoints.cpp +++ b/task_02/src/FindCutPoints.cpp @@ -1,26 +1,24 @@ #include "FindCutPoints.hpp" -void FindCutPoint (int &timer, int start, std::vector< std::vector > &graph, std::vector &tin, std::vector &fup, int parent, std::set &cpvec, std::vector used) { - used[start] = 1; - tin[start] = fup[start] = ++timer; - int to; - int children = 0; - for (int i = 0; i < graph[start].size(); ++i) { - to = graph[start][i]; - if (to == parent) continue; - if (used[to]) - fup[start] = std::min(fup[start], tin[to]); - else { - FindCutPoint(timer, to, graph, tin, fup, start, cpvec, used); - fup[start] = std::min(fup[start], fup[to]); - if (fup[to] >= tin[start] && parent != -1) - cpvec.insert(start); - children++; - } +void FindCutPoint(int &timer, int start, std::vector > &graph, + std::vector &tin, std::vector &fup, int parent, + std::set &cpvec, std::vector used) { + used[start] = 1; + tin[start] = fup[start] = ++timer; + int to; + int children = 0; + for (int i = 0; i < graph[start].size(); ++i) { + to = graph[start][i]; + if (to == parent) continue; + if (used[to]) + fup[start] = std::min(fup[start], tin[to]); + else { + FindCutPoint(timer, to, graph, tin, fup, start, cpvec, used); + fup[start] = std::min(fup[start], fup[to]); + if (fup[to] >= tin[start] && parent != -1) cpvec.insert(start); + children++; } - + } } -std::set returnCP (std::set &cpvec) { - return cpvec; -} \ No newline at end of file +std::set returnCP(std::set &cpvec) { return cpvec; } \ No newline at end of file From 6c64a47df6a767550ce113400283a192b10a2139 Mon Sep 17 00:00:00 2001 From: Climentorii <63839123+Climentorii@users.noreply.github.com> Date: Sun, 14 Jan 2024 22:48:15 +0000 Subject: [PATCH 8/8] Addded 3 with tests --- task_03/src/Deijkstra.cpp | 37 ++++++++++++++++++++++++++++ task_03/src/Deijkstra.hpp | 5 ++++ task_03/src/Johnson.cpp | 52 +++++++++++++++++++++++++++++++++++++++ task_03/src/Johnson.hpp | 16 ++++++++++++ task_03/src/main.cpp | 41 +++--------------------------- task_03/src/test.cpp | 42 ++++++++++++++++++++++++++++--- task_04/src/main.cpp | 21 +--------------- 7 files changed, 153 insertions(+), 61 deletions(-) create mode 100644 task_03/src/Deijkstra.cpp create mode 100644 task_03/src/Deijkstra.hpp create mode 100644 task_03/src/Johnson.cpp create mode 100644 task_03/src/Johnson.hpp diff --git a/task_03/src/Deijkstra.cpp b/task_03/src/Deijkstra.cpp new file mode 100644 index 0000000..a2cc7d2 --- /dev/null +++ b/task_03/src/Deijkstra.cpp @@ -0,0 +1,37 @@ +#include "Deijkstra.hpp" + +#include + +const int INF = 1e9; + +std::vector Deijkstra( + int start, std::vector > > &graph) { + if (start < 0) { + throw "Bad Input"; + } + + if (graph.size() == 0) throw "Empty Graph"; + + std::vector dist(graph.size(), INF); + dist[start] = 0; + std::vector used(graph.size()); + + for (int i = 0; i < graph.size(); ++i) { + int closest = -1; + for (int j = 0; j < graph.size(); ++j) { + if (!used[j] && (closest == -1 || dist[closest] > dist[j])) { + closest = j; + } + } + + used[closest] = true; + + for (auto &[to, weight] : graph[closest]) { + if (weight < 0) throw "Negative Weight!"; + if (dist[to] > dist[closest] + weight) { + dist[to] = dist[closest] + weight; + } + } + } + return dist; +} \ No newline at end of file diff --git a/task_03/src/Deijkstra.hpp b/task_03/src/Deijkstra.hpp new file mode 100644 index 0000000..b0850d9 --- /dev/null +++ b/task_03/src/Deijkstra.hpp @@ -0,0 +1,5 @@ +#pragma once +#include + +std::vector Deijkstra( + int start, std::vector > > &graph); \ No newline at end of file diff --git a/task_03/src/Johnson.cpp b/task_03/src/Johnson.cpp new file mode 100644 index 0000000..a706b58 --- /dev/null +++ b/task_03/src/Johnson.cpp @@ -0,0 +1,52 @@ +#include "Johnson.hpp" + +#include "Deijkstra.hpp" + +std::vector> Johnson(std::vector &edges, int m, int n) { + std::vector vec(n, INF); + std::vector tmp_edges = edges; + int v = 0; + vec[v] = 0; + for (int i = 0; i < n; ++i) { + tmp_edges.push_back({n, i, 0}); + } + + m += n; + + std::vector p(n, -1); + int x; + for (int i = 0; i < n; ++i) { + x = -1; + for (int j = 0; j < m; ++j) { + if (vec[tmp_edges[j].a] < INF) { + if (vec[tmp_edges[j].b] > vec[tmp_edges[j].a] + tmp_edges[j].cost) { + vec[tmp_edges[j].b] = std::min( + vec[tmp_edges[j].b], vec[tmp_edges[j].a] + tmp_edges[j].cost); + p[tmp_edges[j].b] = tmp_edges[j].a; + x = tmp_edges[j].b; + } + } + } + } + if (x != -1) { + throw "Negative Cycle"; + } + + for (int i = 0; i < edges.size(); ++i) { + edges[i].cost = edges[i].cost + vec[edges[i].a] - vec[edges[i].b]; + } + std::vector> res; + + std::vector>> graph; + graph.resize(n); + + for (int i = 0; i < edges.size(); ++i) { + graph[edges[i].a].push_back({edges[i].b, edges[i].cost}); + } + + for (int i = 0; i < n; ++i) { + res.push_back(Deijkstra(i, graph)); + } + + return res; +} \ No newline at end of file diff --git a/task_03/src/Johnson.hpp b/task_03/src/Johnson.hpp new file mode 100644 index 0000000..078373c --- /dev/null +++ b/task_03/src/Johnson.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "Deijkstra.hpp" + +const int INF = 1e9; + +class edge { + public: + int a; + int b; + int cost; +}; + +std::vector> Johnson(std::vector &edges, int m, int n); \ No newline at end of file diff --git a/task_03/src/main.cpp b/task_03/src/main.cpp index 46a12b3..e6faa61 100644 --- a/task_03/src/main.cpp +++ b/task_03/src/main.cpp @@ -1,42 +1,7 @@ #include #include -const int INF = 1e9; +#include "Deijkstra.hpp" +#include "Johnson.hpp" -class edge { - public: - int a; - int b; - int cost; -}; - -int main() { - int n = 5, m = 8; - - std::vector vec(n, INF); - std::vector edges = {{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, {1, 3, 2}, - {1, 4, 2}, {3, 2, 5}, {3, 1, 1}, {4, 3, -3}}; - int v = 0; - vec[v] = 0; - std::vector p(n, -1); - int x; - for (int i = 0; i < n; ++i) { - x = -1; - for (int j = 0; j < m; ++j) { - if (vec[edges[j].a] < INF) { - if (vec[edges[j].b] > vec[edges[j].a] + edges[j].cost) { - vec[edges[j].b] = std::max(-INF, vec[edges[j].a] + edges[j].cost); - p[edges[j].b] = edges[j].a; - x = edges[j].b; - } - } - } - } - if (x != -1) { - throw "Negative Cycle"; - } - - for (auto i : vec) { - std::cout << i << " "; - } -} \ No newline at end of file +int main() {} \ No newline at end of file diff --git a/task_03/src/test.cpp b/task_03/src/test.cpp index 5e11617..4a90e84 100644 --- a/task_03/src/test.cpp +++ b/task_03/src/test.cpp @@ -1,6 +1,42 @@ - #include -TEST(TopologySort, Simple) { - ASSERT_EQ(1, 1); // Stack [] +#include "Deijkstra.hpp" +#include "Johnson.hpp" + +TEST(Jonson, Test1) { + std::vector edges = {{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, {1, 3, 2}, + {1, 4, 2}, {3, 2, 5}, {3, 1, 1}, {4, 3, -3}}; + std::vector> d = Johnson(edges, 8, 5); + std::vector> result = { + {0, 1, 2, 1, 1}, + {1000000000, 0, 1, 0, 0}, + {1000000000, 1000000000, 0, 1000000000, 1000000000}, + {1000000000, 0, 1, 0, 0}, + {1000000000, 0, 1, 0, 0}}; + ASSERT_EQ(d, result); } + +TEST(Jonson, NegativeCycle) { + std::vector edges = {{0, 5, 1}, {1, 0, 1}, {2, 1, 1}, {2, 3, 1}, + {3, 4, 1}, {4, 5, 1}, {5, 5, -10}, {5, 2, 3}}; + ASSERT_ANY_THROW(Johnson(edges, 8, 5)); +} + +TEST(Jonson, Test2) { + std::vector edges = {{0, 1, 1}, {0, 2, -2}, {1, 3, 10}, {3, 6, 1}, + {1, 6, -3}, {6, 2, 5}, {2, 5, -1}, {2, 4, 2}, + {5, 4, 2}, {6, 7, 10}, {5, 7, -3}}; + std::vector> d = Johnson(edges, 11, 8); + std::vector> result = { + {0, 1, 0, 11, 0, 0, 1, 0}, + {1000000000, 0, 4, 10, 4, 4, 0, 4}, + {1000000000, 1000000000, 0, 1000000000, 0, 0, 1000000000, 0}, + {1000000000, 1000000000, 8, 0, 8, 8, 4, 8}, + {1000000000, 1000000000, 1000000000, 1000000000, 0, 1000000000, + 1000000000, 1000000000}, + {1000000000, 1000000000, 1000000000, 1000000000, 0, 0, 1000000000, 0}, + {1000000000, 1000000000, 4, 1000000000, 4, 4, 0, 4}, + {1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, + 1000000000, 0}}; + ASSERT_EQ(d, result); +} \ No newline at end of file diff --git a/task_04/src/main.cpp b/task_04/src/main.cpp index 6c6d1b9..5913ffd 100644 --- a/task_04/src/main.cpp +++ b/task_04/src/main.cpp @@ -5,23 +5,4 @@ using namespace std; -int main() { - int n, m; - cin >> n >> m; - - vector > > graph; - graph.resize(n); - - int from, to, weight; - - for (int i = 0; i < m; ++i) { - cin >> from >> to >> weight; - graph[from].push_back({to, weight}); - } - - int start, end; - cin >> start >> end; - int k = Deijkstra(start, end, graph); - - cout << k; -} \ No newline at end of file +int main() {} \ No newline at end of file