From 4b10ac95f09a87a3f9270aeacb0c887ec592c50a Mon Sep 17 00:00:00 2001 From: Fedor Date: Sat, 21 Oct 2023 11:40:12 +0300 Subject: [PATCH 1/5] Solved 4 problems + Graphs Solved problems: - Triangle of sticks - Colored cube - Anton and watermelons - Paid musical service Graphs: - Implemented Graph - Made Add/Remove functions for vertexes and edges. --- .../Anton_and_watermelons.cpp | 48 +++++++++++++++++ .../Olympiada 2023-2024/Colored_cube.cpp | 46 ++++++++++++++++ .../Triangle_of_sticks.cpp | 45 ++++++++++++++++ .../paid_musical_services.cpp | 46 ++++++++++++++++ Data_Structures/Graph/Graph.cpp | 10 ++++ Data_Structures/Graph/Graph.h | 54 +++++++++++++++++++ Data_Structures/Graph/Graph_Interface.h | 33 ++++++++++++ 7 files changed, 282 insertions(+) create mode 100644 Algoritms/Olympiada 2023-2024/Anton_and_watermelons.cpp create mode 100644 Algoritms/Olympiada 2023-2024/Colored_cube.cpp create mode 100644 Algoritms/Olympiada 2023-2024/Triangle_of_sticks.cpp create mode 100644 Algoritms/Olympiada 2023-2024/paid_musical_services.cpp create mode 100644 Data_Structures/Graph/Graph.cpp create mode 100644 Data_Structures/Graph/Graph.h create mode 100644 Data_Structures/Graph/Graph_Interface.h diff --git a/Algoritms/Olympiada 2023-2024/Anton_and_watermelons.cpp b/Algoritms/Olympiada 2023-2024/Anton_and_watermelons.cpp new file mode 100644 index 0000000..284df89 --- /dev/null +++ b/Algoritms/Olympiada 2023-2024/Anton_and_watermelons.cpp @@ -0,0 +1,48 @@ +// Copyright 2022 Zener +// Шаблон для олимпиадных задач + +#include + +using namespace std; + +void solve(); + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(nullptr); + +#ifndef ONLINE_JUDGE + freopen("input.txt", "r", stdin); + freopen("error.txt", "w", stderr); + freopen("output.txt", "w", stdout); +#endif + + int t = 1; + // /*is Single Test case?*/ cin >> t; + while (t--) { + solve(); + cout << "\n"; + } + + cerr << "time taken : " << (float) clock() / CLOCKS_PER_SEC << " secs" << endl; + return 0; +} + +void solve() { + long long n, m, d, temp; + cin >> n >> m >> d; + vector vec_x; + vector vec_y; + for(int i = 0; i < d; ++i){ + cin >> temp; + vec_x.push_back(temp); + cin >> temp; + vec_y.push_back(temp); + } + long long x = vec_x[0], y = vec_y[0]; + for(int i = 0; i < d; ++i){ + x = min(x, vec_x[i]); + y = min(y, vec_y[i]); + } + cout << x * y << " " << d; +} diff --git a/Algoritms/Olympiada 2023-2024/Colored_cube.cpp b/Algoritms/Olympiada 2023-2024/Colored_cube.cpp new file mode 100644 index 0000000..2e5bb26 --- /dev/null +++ b/Algoritms/Olympiada 2023-2024/Colored_cube.cpp @@ -0,0 +1,46 @@ +// Copyright 2022 Zener +// Шаблон для олимпиадных задач + +#include + +using namespace std; + +void solve(); + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(nullptr); + +#ifndef ONLINE_JUDGE + freopen("input.txt", "r", stdin); + freopen("error.txt", "w", stderr); + freopen("output.txt", "w", stdout); +#endif + + int t = 1; + // /*is Single Test case?*/ cin >> t; + while (t--) { + solve(); + cout << "\n"; + } + + cerr << "time taken : " << (float) clock() / CLOCKS_PER_SEC << " secs" << endl; + return 0; +} + +void solve() { + int n, f; + cin >> n >> f; + if(f == 0){ + cout << (n - 2) * (n - 2); + } + else if(f == 1){ + cout << (n - 2) * (n - 2) * 6; + } + else if(f == 2){ + cout << (n - 2) * 12; + } + else if(f == 3){ + cout << 8; + } +} diff --git a/Algoritms/Olympiada 2023-2024/Triangle_of_sticks.cpp b/Algoritms/Olympiada 2023-2024/Triangle_of_sticks.cpp new file mode 100644 index 0000000..aa8ac63 --- /dev/null +++ b/Algoritms/Olympiada 2023-2024/Triangle_of_sticks.cpp @@ -0,0 +1,45 @@ +// Copyright 2022 Zener +// Шаблон для олимпиадных задач + +#include + +using namespace std; + +void solve(); + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(nullptr); + +#ifndef ONLINE_JUDGE + freopen("input.txt", "r", stdin); + freopen("error.txt", "w", stderr); + freopen("output.txt", "w", stdout); +#endif + + int t = 1; + // /*is Single Test case?*/ cin >> t; + while (t--) { + solve(); + cout << "\n"; + } + + cerr << "time taken : " << (float) clock() / CLOCKS_PER_SEC << " secs" << endl; + return 0; +} + +void solve() { + long long a, b, c; + cin >> a >> b >> c; + long long x; + x = max(max(a, b), c); + if(a == x){ + cout << b + c - a; + } + else if(b == x){ + cout << a + c - b; + } + else{ + cout << a + b - c; + } +} diff --git a/Algoritms/Olympiada 2023-2024/paid_musical_services.cpp b/Algoritms/Olympiada 2023-2024/paid_musical_services.cpp new file mode 100644 index 0000000..b58ae5f --- /dev/null +++ b/Algoritms/Olympiada 2023-2024/paid_musical_services.cpp @@ -0,0 +1,46 @@ +// Copyright 2022 Zener +// Шаблон для олимпиадных задач + +#include + +using namespace std; + +void solve(); + +int main() { + ios_base::sync_with_stdio(false); + cin.tie(nullptr); + +#ifndef ONLINE_JUDGE + freopen("input.txt", "r", stdin); + freopen("error.txt", "w", stderr); + freopen("output.txt", "w", stdout); +#endif + + int t = 1; + // /*is Single Test case?*/ cin >> t; + while (t--) { + solve(); + cout << "\n"; + } + + cerr << "time taken : " << (float) clock() / CLOCKS_PER_SEC << " secs" << endl; + return 0; +} + +void solve() { + long long n, m; + cin >> n >> m; + long long a = 1, d = 1, ans = 0; + while(d <= m){ + if((a + (n - 1) * d) <= m){ + ans += 1; + a += 1; + } + else{ + d += 1; + a = 1; + } + } + cout << ans; +} diff --git a/Data_Structures/Graph/Graph.cpp b/Data_Structures/Graph/Graph.cpp new file mode 100644 index 0000000..17cb0cb --- /dev/null +++ b/Data_Structures/Graph/Graph.cpp @@ -0,0 +1,10 @@ +// +// Created by User on 15.10.2023. +// + +#include +#include "Graph.h" + +int main() { + cout << " "; +} diff --git a/Data_Structures/Graph/Graph.h b/Data_Structures/Graph/Graph.h new file mode 100644 index 0000000..f53e8a1 --- /dev/null +++ b/Data_Structures/Graph/Graph.h @@ -0,0 +1,54 @@ +// +// Created by User on 15.10.2023. +// + +#ifndef COMPETITIVE_PROGRAMMING_GRAPH_H +#define COMPETITIVE_PROGRAMMING_GRAPH_H + +#include "Graph_Interface.h" +#include +#include + +using namespace std; + +template +class Graph : public GraphInterface { + vector _vertexes; + vector _edges; + + public: + Graph() = default; + + vector vertexes() override { + return _vertexes; + } + + vector edges() override { + return _edges; + } + + void add_vertex(V vertex) override { + _vertexes.push_back(vertex); + } + + void add_edge(V v1, V v2) override { + _edges.push_back(E(v1, v2)); + } + + void remove_vertex(V vertex) override { + auto index = find(_vertexes.begin(), _vertexes.end(), vertex); + if (index != _vertexes.end()) _vertexes.erase(index); + } + + void remove_edge(E edge) override { +// ДЗ + } + + V *path(V v1, V v2) override { +// ДЗ - Поиск в ширину + return nullptr; + } +}; + + +#endif //COMPETITIVE_PROGRAMMING_GRAPH_H diff --git a/Data_Structures/Graph/Graph_Interface.h b/Data_Structures/Graph/Graph_Interface.h new file mode 100644 index 0000000..d43cb06 --- /dev/null +++ b/Data_Structures/Graph/Graph_Interface.h @@ -0,0 +1,33 @@ +// +// Created by Zener085 on 15.10.2023. +// + +#ifndef COMPETITIVE_PROGRAMMING_GRAPH_INTERFACE_H +#define COMPETITIVE_PROGRAMMING_GRAPH_INTERFACE_H + +#include + +using namespace std; + +template +class GraphInterface { + /** + * Возвращает все узлы графа + * @return Массив узлов графа + */ + virtual vector vertexes() = 0; + + /** + * Возвращает все линии графа + * @return Массив линий графа + */ + virtual vector edges() = 0; + virtual void add_vertex(V vertex) = 0; + virtual void add_edge(V v1, V v2) = 0; + virtual void remove_vertex(V vertex) = 0; + virtual void remove_edge(E edge) = 0; + + virtual V *path(V v1, V v2) = 0; +}; + +#endif //COMPETITIVE_PROGRAMMING_GRAPH_INTERFACE_H \ No newline at end of file From 597fbb4074bf32cd1c0fe09352b9b63092d95e2c Mon Sep 17 00:00:00 2001 From: Fedor Date: Sat, 21 Oct 2023 14:51:16 +0300 Subject: [PATCH 2/5] Graphs and resolved Paid musical services problem --- .../paid_musical_services.cpp | 7 ++-- Data_Structures/Graph/Graph.h | 37 ++++++++++++++++++- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/Algoritms/Olympiada 2023-2024/paid_musical_services.cpp b/Algoritms/Olympiada 2023-2024/paid_musical_services.cpp index b58ae5f..e06c103 100644 --- a/Algoritms/Olympiada 2023-2024/paid_musical_services.cpp +++ b/Algoritms/Olympiada 2023-2024/paid_musical_services.cpp @@ -33,13 +33,12 @@ void solve() { cin >> n >> m; long long a = 1, d = 1, ans = 0; while(d <= m){ - if((a + (n - 1) * d) <= m){ - ans += 1; - a += 1; + if((n - 1) * d <= m){ + ans += m - (n - 1) * d; + d += 1; } else{ d += 1; - a = 1; } } cout << ans; diff --git a/Data_Structures/Graph/Graph.h b/Data_Structures/Graph/Graph.h index f53e8a1..4451de5 100644 --- a/Data_Structures/Graph/Graph.h +++ b/Data_Structures/Graph/Graph.h @@ -41,11 +41,44 @@ class Graph : public GraphInterface { } void remove_edge(E edge) override { -// ДЗ + auto index = find(_edges.begin(), _edges.end(), edge); + _edges.erase(index); + } + + int MinDist(int distance[], bool visit[]){ + int minimum = INT_MAX, ind; + for(int i = 0; i < _edges.size(); ++i){ + if(visit[i] == false && distance[i] <= minimum){ + minimum = distance[i]; + ind = i; + } + } + return ind; } V *path(V v1, V v2) override { -// ДЗ - Поиск в ширину + int distance[_edges.size()]; + bool visit[_edges.size()]; + for(int i = 0; i < _edges.size(); i++) + { + distance[i] = INT_MAX; + visit[i] = false; + } + distance[v1] = 0; + for(int i = 0; i < _edges.size(); ++i){ + int m = MinDist(distance, visit); + visit[m] = true; + for(int j = 0; j < _edges.size(); ++j){ + if(!visit[j] && _edges[m][j] && distance[m] != INT_MAX && distance[m]+_edges[m][j] < distance[j]){ + distance[j] = distance[m] + _edges[m][j]; + } + } + } + for(int i = 0; i < _edges.size(); i++){ + char str = 65 + i; + cout << str << "\t\t\t" << distance[i] << endl; + } + return nullptr; } }; From e8c1158691b78b3ac048bbf28d2e7c73e109eaf8 Mon Sep 17 00:00:00 2001 From: Zener_085 <57841939+Zener085@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:34:37 +0300 Subject: [PATCH 3/5] Graph usage example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Пример использования графа --- Data_Structures/Graph/Graph.cpp | 57 ++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/Data_Structures/Graph/Graph.cpp b/Data_Structures/Graph/Graph.cpp index 17cb0cb..066224b 100644 --- a/Data_Structures/Graph/Graph.cpp +++ b/Data_Structures/Graph/Graph.cpp @@ -5,6 +5,61 @@ #include #include "Graph.h" +struct Road { + string city1; + string city2; + int length; + Road(string city1, string city2, int length) { + this->city1 = city1; + this->city2 = city2; + this->length = length; + } + Road(string city1, string city2) { + this->city1 = city1; + this->city2 = city2; + this->length = 1; + } +}; + int main() { - cout << " "; + // Пару городов + string msk = "Moscow"; + string piter = "Saint Petersburg"; + string kzn = "Kazan"; + string inno = "Innopolis"; + + Graph g; + + g.add_vertex(msk); + g.add_vertex(piter); + g.add_vertex(kzn); + g.add_vertex(inno); + + g.add_edge(msk, piter); + g.add_edge(msk, kzn); + g.add_edge(piter, kzn); + g.add_edge(kzn, inno); + + g.edges()[0].length = 400; + g.edges()[1].length = 680; + g.edges()[2].length = 1200; + g.edges()[3].length = 42; + + // Просто должно работать "Moscow Piter" + for (string city : g.path(msk, piter)) { + cout << city << " "; + } + cout << "\n"; + + // Проверка, сможет ли метод вернуть больше одного города. "Moscow Kazan Innopolis" + for (string city : g.path(msk, inno)) { + cout << city << " "; + } + cout << "\n"; + + // Проверка, сможет ли метод найти путь покороче. Правильный ответ: "Saint Petersburg Moscow Kazan" + for (string city : g.path(piter, kzn)) { + cout << city << " "; + } + cout << "\n"; } From 836623e23c3f4713f240a0c53ea35aa3f3cc32b2 Mon Sep 17 00:00:00 2001 From: Fedor Date: Sat, 28 Oct 2023 14:00:55 +0300 Subject: [PATCH 4/5] Graphs Made a Graph algorythm which can find the shortest way between two objects. --- Data_Structures/Graph/Graph.cpp | 22 +--- Data_Structures/Graph/Graph.h | 152 +++++++++++++++++++----- Data_Structures/Graph/Graph_Interface.h | 2 +- 3 files changed, 128 insertions(+), 48 deletions(-) diff --git a/Data_Structures/Graph/Graph.cpp b/Data_Structures/Graph/Graph.cpp index 066224b..811fcb0 100644 --- a/Data_Structures/Graph/Graph.cpp +++ b/Data_Structures/Graph/Graph.cpp @@ -5,23 +5,14 @@ #include #include "Graph.h" -struct Road { - string city1; - string city2; - int length; - Road(string city1, string city2, int length) { - this->city1 = city1; - this->city2 = city2; - this->length = length; - } - Road(string city1, string city2) { - this->city1 = city1; - this->city2 = city2; - this->length = 1; - } -}; int main() { + #ifndef ONLINE_JUDGE + freopen("input.txt", "r", stdin); + freopen("error.txt", "w", stderr); + freopen("output.txt", "w", stdout); + #endif + // Пару городов string msk = "Moscow"; string piter = "Saint Petersburg"; @@ -44,7 +35,6 @@ int main() { g.edges()[1].length = 680; g.edges()[2].length = 1200; g.edges()[3].length = 42; - // Просто должно работать "Moscow Piter" for (string city : g.path(msk, piter)) { cout << city << " "; diff --git a/Data_Structures/Graph/Graph.h b/Data_Structures/Graph/Graph.h index 4451de5..ca08437 100644 --- a/Data_Structures/Graph/Graph.h +++ b/Data_Structures/Graph/Graph.h @@ -11,6 +11,22 @@ using namespace std; +struct Road { + string city1; + string city2; + int length; + Road(string city1, string city2, int length) { + this->city1 = city1; + this->city2 = city2; + this->length = length; + } + Road(string city1, string city2) { + this->city1 = city1; + this->city2 = city2; + this->length = 1; + } +}; + template class Graph : public GraphInterface { vector _vertexes; @@ -41,47 +57,121 @@ class Graph : public GraphInterface { } void remove_edge(E edge) override { - auto index = find(_edges.begin(), _edges.end(), edge); - _edges.erase(index); +// auto index = find(_edges.begin(), _edges.end(), edge); +// _edges.erase(index); } - int MinDist(int distance[], bool visit[]){ - int minimum = INT_MAX, ind; - for(int i = 0; i < _edges.size(); ++i){ - if(visit[i] == false && distance[i] <= minimum){ - minimum = distance[i]; - ind = i; + vector path(V v1, V v2) override { + unordered_set visited; // Множество посещённых городов + vector visited_edges; // Множество посещённых рёбер + vector path; // Путь от одной точки до другой + queue next; // Очередь вершин которые нужно пройти после текущей + next.push(v1); // Добавление первой вершины + while (!next.empty()) { // Пока у вершины не будет соседствующих вершин + V actual = next.back(); // Вытаскиваем вершину из очереди + next.pop(); + if (visited.contains(actual)) // Если уже прошлись по этой вершине, то скип + continue; + visited.insert(actual); + if (actual == v2) { // Если мы дошли до искомого элемента, заканчиваем цикл + break; + } + for (E edge : this->_edges) { // Проход по всем ребрам + if (edge.city1 == actual && !visited.contains(edge.city2)) { // Если есть путь до вершины, то добавляем её в очередь (идём дальше) + next.push(edge.city2); + visited_edges.push_back(edge); + } else if (edge.city2 == actual && !visited.contains(edge.city1)) { + next.push(edge.city1); + visited_edges.push_back(edge); + } } } - return ind; - } - - V *path(V v1, V v2) override { - int distance[_edges.size()]; - bool visit[_edges.size()]; - for(int i = 0; i < _edges.size(); i++) - { - distance[i] = INT_MAX; - visit[i] = false; - } - distance[v1] = 0; - for(int i = 0; i < _edges.size(); ++i){ - int m = MinDist(distance, visit); - visit[m] = true; - for(int j = 0; j < _edges.size(); ++j){ - if(!visit[j] && _edges[m][j] && distance[m] != INT_MAX && distance[m]+_edges[m][j] < distance[j]){ - distance[j] = distance[m] + _edges[m][j]; + visited.clear(); + V next_vertex = v2; // Текущая вершина которая будет записана в путь + while (!visited.contains(v1)) { + for (E edge : visited_edges) { // Проход по всем ребрам + if (edge.city1 == next_vertex) { // Если нашли ребро с текущей вершиной, то переходим к новой вершине + visited.insert(next_vertex); + next_vertex = edge.city2; + break; + } else if (edge.city2 == next_vertex) { + visited.insert(next_vertex); + next_vertex = edge.city1; + break; } } } - for(int i = 0; i < _edges.size(); i++){ - char str = 65 + i; - cout << str << "\t\t\t" << distance[i] << endl; + for (V v : visited) { + path.push_back(v); } - - return nullptr; + return path; } }; +// vector path(V v1, V v2) override { +// unordered_set visited; // Множество посещённых городов +// vector visited_edges; // Множество посещённых рёбер +// vector path; // Путь от одной точки до другой +// +// priority_queue, vector>, greater>> next; // Очередь вершин которые нужно пройти после текущей +// next.push(make_pair(0, v1)); // Добавление первой вершины +// unordered_map previous; +// +// while (!next.empty()) { // Пока у вершины не будет соседствующих вершин +// V actual = next.top().second; // Вытаскиваем вершину из очереди +// next.pop(); +// +// if (visited.contains(actual)) // Если уже прошлись по этой вершине, то скип +// continue; +// visited.insert(actual); +// +// if (actual == v2) { // Если мы дошли до искомого элемента, заканчиваем цикл +// break; +// } +// +// for (E edge : this->_edges) { // Проход по всем ребрам +// if (edge.city1 == actual && !visited.contains(edge.city2)) { +// int newDistance = _edges[actual] + edge.weight; +// if (newDistance < _edges[edge.city2]) { // Если есть путь до вершины, то добавляем её в очередь (идём дальше) +// next.push(make_pair(newDistance, edge.city2)); +// previous[edge.city2] = actual; +// visited_edges.push_back(edge); +// } +// } else if (edge.city2 == actual && !visited.contains(edge.city1)) { +// int newDistance = _edges[actual] + edge.weight; +// if (newDistance < _edges[edge.city1]) { +// next.push(make_pair(newDistance, edge.city1)); +// previous[edge.city1] = actual; +// visited_edges.push_back(edge); +// } +// } +// } +// } +// visited.clear(); +// V next_vertex = v2; // Текущая вершина которая будет записана в путь +// while (!visited.contains(v1)) { +// for (E edge : visited_edges) { // Проход по всем ребрам +// if (edge.city1 == next_vertex) { // Если нашли ребро с текущей вершиной, то переходим к новой вершине +// visited.insert(next_vertex); +// next_vertex = edge.city2; +// break; +// } else if (edge.city2 == next_vertex) { +// visited.insert(next_vertex); +// next_vertex = edge.city1; +// break; +// } +// } +// } +// V nextVertex = v2; +// while (nextVertex != v1) { +// path.push_back(nextVertex); +// nextVertex = previous[nextVertex]; +// } +// path.push_back(v1); +// reverse(path.begin(), path.end()); +// return path; +// } +//}; + #endif //COMPETITIVE_PROGRAMMING_GRAPH_H diff --git a/Data_Structures/Graph/Graph_Interface.h b/Data_Structures/Graph/Graph_Interface.h index d43cb06..5673c51 100644 --- a/Data_Structures/Graph/Graph_Interface.h +++ b/Data_Structures/Graph/Graph_Interface.h @@ -27,7 +27,7 @@ class GraphInterface { virtual void remove_vertex(V vertex) = 0; virtual void remove_edge(E edge) = 0; - virtual V *path(V v1, V v2) = 0; + virtual vector path(V v1, V v2) = 0; }; #endif //COMPETITIVE_PROGRAMMING_GRAPH_INTERFACE_H \ No newline at end of file From 1113d299f42909e4f893a936b0ea9343ae9dc694 Mon Sep 17 00:00:00 2001 From: Fedor Date: Fri, 17 Nov 2023 19:54:17 +0300 Subject: [PATCH 5/5] Graphs are finaly done! - Fully made Dijkstra's algorithm - Started making DFS algorithm --- Data_Structures/Graph/Graph.cpp | 18 +++- Data_Structures/Graph/Graph.h | 186 ++++++++++++++------------------ 2 files changed, 97 insertions(+), 107 deletions(-) diff --git a/Data_Structures/Graph/Graph.cpp b/Data_Structures/Graph/Graph.cpp index 811fcb0..05a734b 100644 --- a/Data_Structures/Graph/Graph.cpp +++ b/Data_Structures/Graph/Graph.cpp @@ -18,18 +18,28 @@ int main() { string piter = "Saint Petersburg"; string kzn = "Kazan"; string inno = "Innopolis"; + string ekat = "Ekaterinburg"; + string vlad = "Vladivostok"; + string pskov = "Pskov"; - Graph g; + Graph g; g.add_vertex(msk); g.add_vertex(piter); g.add_vertex(kzn); g.add_vertex(inno); + g.add_vertex(ekat); + g.add_vertex(vlad); + g.add_vertex(pskov); g.add_edge(msk, piter); g.add_edge(msk, kzn); g.add_edge(piter, kzn); g.add_edge(kzn, inno); + g.add_edge(kzn, ekat); + g.add_edge(ekat, vlad); + g.add_edge(vlad, pskov); + g.add_edge(msk, pskov); g.edges()[0].length = 400; g.edges()[1].length = 680; @@ -52,4 +62,10 @@ int main() { cout << city << " "; } cout << "\n"; + + vector cities = g.path(piter, pskov); + for (string city : cities) { + cout << city << " "; + } + cout << "\n"; } diff --git a/Data_Structures/Graph/Graph.h b/Data_Structures/Graph/Graph.h index ca08437..c1f6093 100644 --- a/Data_Structures/Graph/Graph.h +++ b/Data_Structures/Graph/Graph.h @@ -10,6 +10,7 @@ #include using namespace std; +typedef pair psi; struct Road { string city1; @@ -27,10 +28,10 @@ struct Road { } }; -template -class Graph : public GraphInterface { +template +class Graph : public GraphInterface { vector _vertexes; - vector _edges; + vector _edges; public: Graph() = default; @@ -39,7 +40,7 @@ class Graph : public GraphInterface { return _vertexes; } - vector edges() override { + vector edges() override { return _edges; } @@ -48,7 +49,7 @@ class Graph : public GraphInterface { } void add_edge(V v1, V v2) override { - _edges.push_back(E(v1, v2)); + _edges.push_back(Road(v1, v2)); } void remove_vertex(V vertex) override { @@ -56,122 +57,95 @@ class Graph : public GraphInterface { if (index != _vertexes.end()) _vertexes.erase(index); } - void remove_edge(E edge) override { + void remove_edge(Road edge) override { // auto index = find(_edges.begin(), _edges.end(), edge); // _edges.erase(index); } - vector path(V v1, V v2) override { - unordered_set visited; // Множество посещённых городов - vector visited_edges; // Множество посещённых рёбер - vector path; // Путь от одной точки до другой - queue next; // Очередь вершин которые нужно пройти после текущей - next.push(v1); // Добавление первой вершины - while (!next.empty()) { // Пока у вершины не будет соседствующих вершин - V actual = next.back(); // Вытаскиваем вершину из очереди + vector djkst(V v1, V v2) { + unordered_map> paths; + vector start(1, v1); + paths[v1] = start; + + unordered_set path_exist; + path_exist.insert(v1); + + queue next; + next.push(v1); + + unordered_set visited; + + while (!next.empty()) { + V actual = next.front(); next.pop(); - if (visited.contains(actual)) // Если уже прошлись по этой вершине, то скип - continue; + + if (visited.contains(actual)) continue; visited.insert(actual); - if (actual == v2) { // Если мы дошли до искомого элемента, заканчиваем цикл - break; - } - for (E edge : this->_edges) { // Проход по всем ребрам - if (edge.city1 == actual && !visited.contains(edge.city2)) { // Если есть путь до вершины, то добавляем её в очередь (идём дальше) - next.push(edge.city2); - visited_edges.push_back(edge); - } else if (edge.city2 == actual && !visited.contains(edge.city1)) { - next.push(edge.city1); - visited_edges.push_back(edge); + + for (Road edge : this->_edges) { + if (edge.city1 == actual) { + V neigh = edge.city2; + + if (!path_exist.contains(neigh) || paths[neigh].size() > paths[actual].size() + 1) { + paths[neigh] = paths[actual]; + paths[neigh].push_back(neigh); + next.push(neigh); + if (visited.contains(neigh)) visited.erase(neigh); + if (!path_exist.contains(neigh)) path_exist.insert(neigh); + } + } else if (edge.city2 == actual) { + V neigh = edge.city1; + + if (!path_exist.contains(neigh) || paths[neigh].size() > paths[actual].size() + 1) { + paths[neigh] = paths[actual]; + paths[neigh].push_back(neigh); + next.push(neigh); + if (visited.contains(neigh)) visited.erase(neigh); + if (!path_exist.contains(neigh)) path_exist.insert(neigh); + } } } } - visited.clear(); - V next_vertex = v2; // Текущая вершина которая будет записана в путь - while (!visited.contains(v1)) { - for (E edge : visited_edges) { // Проход по всем ребрам - if (edge.city1 == next_vertex) { // Если нашли ребро с текущей вершиной, то переходим к новой вершине - visited.insert(next_vertex); - next_vertex = edge.city2; - break; - } else if (edge.city2 == next_vertex) { - visited.insert(next_vertex); - next_vertex = edge.city1; - break; + return paths[v2]; + } + + vector dfs(V actual, V v2, set visited, vector path) { + path.push_back(actual); + if (actual == v2) return path; + + if (visited.contains(actual)) { + path.pop_back(); + return path; + } + + visited.insert(actual); + + for (Road edge : this->_edges) { + if (edge.city1 == actual) { + vector new_path = dfs(edge.city2, v2, visited, path); + if (new_path.size() == path.size()) { + continue; + } + return new_path; + } else if (edge.city2 == actual) { + vector new_path = dfs(edge.city1, v2, visited, path); + if (new_path.size() == path.size()) { + continue; } + return new_path; } } - for (V v : visited) { - path.push_back(v); - } + path.pop_back(); return path; } -}; -// vector path(V v1, V v2) override { -// unordered_set visited; // Множество посещённых городов -// vector visited_edges; // Множество посещённых рёбер -// vector path; // Путь от одной точки до другой -// -// priority_queue, vector>, greater>> next; // Очередь вершин которые нужно пройти после текущей -// next.push(make_pair(0, v1)); // Добавление первой вершины -// unordered_map previous; -// -// while (!next.empty()) { // Пока у вершины не будет соседствующих вершин -// V actual = next.top().second; // Вытаскиваем вершину из очереди -// next.pop(); -// -// if (visited.contains(actual)) // Если уже прошлись по этой вершине, то скип -// continue; -// visited.insert(actual); -// -// if (actual == v2) { // Если мы дошли до искомого элемента, заканчиваем цикл -// break; -// } -// -// for (E edge : this->_edges) { // Проход по всем ребрам -// if (edge.city1 == actual && !visited.contains(edge.city2)) { -// int newDistance = _edges[actual] + edge.weight; -// if (newDistance < _edges[edge.city2]) { // Если есть путь до вершины, то добавляем её в очередь (идём дальше) -// next.push(make_pair(newDistance, edge.city2)); -// previous[edge.city2] = actual; -// visited_edges.push_back(edge); -// } -// } else if (edge.city2 == actual && !visited.contains(edge.city1)) { -// int newDistance = _edges[actual] + edge.weight; -// if (newDistance < _edges[edge.city1]) { -// next.push(make_pair(newDistance, edge.city1)); -// previous[edge.city1] = actual; -// visited_edges.push_back(edge); -// } -// } -// } -// } -// visited.clear(); -// V next_vertex = v2; // Текущая вершина которая будет записана в путь -// while (!visited.contains(v1)) { -// for (E edge : visited_edges) { // Проход по всем ребрам -// if (edge.city1 == next_vertex) { // Если нашли ребро с текущей вершиной, то переходим к новой вершине -// visited.insert(next_vertex); -// next_vertex = edge.city2; -// break; -// } else if (edge.city2 == next_vertex) { -// visited.insert(next_vertex); -// next_vertex = edge.city1; -// break; -// } -// } -// } -// V nextVertex = v2; -// while (nextVertex != v1) { -// path.push_back(nextVertex); -// nextVertex = previous[nextVertex]; -// } -// path.push_back(v1); -// reverse(path.begin(), path.end()); -// return path; -// } -//}; + vector path(V v1, V v2) override { + vector path; + set visited; + + return dfs(v1, v2, visited, path); + } +}; #endif //COMPETITIVE_PROGRAMMING_GRAPH_H