diff --git a/readme.md b/readme.md
index f57085f09..bc55aad54 100644
--- a/readme.md
+++ b/readme.md
@@ -18,7 +18,7 @@
| № | ФИО | Directory name | #0 | #1 | #2 | #3 | #4 | #5 | #6 | #7 | Рейтинг |
|----|------------------------------------------------------|-------------------------|----|-----|----|----|----|----|----|----|---------|
| 1 | Бусень Артём |[ii02301](trunk/ii02301) | ✅ | ✅ | ❌ | ❌ | ✅ | | | | 6|
-| 2 | [Волкогон Никита](https://github.com/VolkogonNikita) |[ii02302](trunk/ii02302) | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | | | 8|
+| 2 | [Волкогон Никита](https://github.com/VolkogonNikita) |[ii02302](trunk/II02302) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | 9|
| 3 | [Вышинский Артём](https://github.com/arciomwww) |[ii02303](trunk/ii02303) | ✅ | ✅ | ❌ | ❌ | | | | | 6|
| 4 | [Гавришук Владислав](https://github.com/VLadGavrishuk)|[ii02304](trunk/ii02304)| ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | | | 7|
| 5 | Глухарев Даниил |[ii02305](trunk/ii02305) | ✅ | ✅ | ✅ | ❌ | | | | | 7|
diff --git a/trunk/II02302/task_03/doc/1.png b/trunk/II02302/task_03/doc/1.png
new file mode 100644
index 000000000..23bcff185
Binary files /dev/null and b/trunk/II02302/task_03/doc/1.png differ
diff --git a/trunk/II02302/task_03/doc/2.png b/trunk/II02302/task_03/doc/2.png
new file mode 100644
index 000000000..447ff2b0e
Binary files /dev/null and b/trunk/II02302/task_03/doc/2.png differ
diff --git a/trunk/II02302/task_03/doc/3.png b/trunk/II02302/task_03/doc/3.png
new file mode 100644
index 000000000..3a2d2a6c5
Binary files /dev/null and b/trunk/II02302/task_03/doc/3.png differ
diff --git a/trunk/II02302/task_03/doc/4.png b/trunk/II02302/task_03/doc/4.png
new file mode 100644
index 000000000..04f270d7d
Binary files /dev/null and b/trunk/II02302/task_03/doc/4.png differ
diff --git a/trunk/II02302/task_03/doc/5.png b/trunk/II02302/task_03/doc/5.png
new file mode 100644
index 000000000..cdcf2cffa
Binary files /dev/null and b/trunk/II02302/task_03/doc/5.png differ
diff --git a/trunk/II02302/task_03/doc/6.png b/trunk/II02302/task_03/doc/6.png
new file mode 100644
index 000000000..b2df0b08f
Binary files /dev/null and b/trunk/II02302/task_03/doc/6.png differ
diff --git a/trunk/II02302/task_03/doc/7.png b/trunk/II02302/task_03/doc/7.png
new file mode 100644
index 000000000..29a560735
Binary files /dev/null and b/trunk/II02302/task_03/doc/7.png differ
diff --git a/trunk/II02302/task_03/doc/8.png b/trunk/II02302/task_03/doc/8.png
new file mode 100644
index 000000000..3fd86646e
Binary files /dev/null and b/trunk/II02302/task_03/doc/8.png differ
diff --git a/trunk/II02302/task_03/doc/report.md b/trunk/II02302/task_03/doc/report.md
new file mode 100644
index 000000000..fffcc59b9
--- /dev/null
+++ b/trunk/II02302/task_03/doc/report.md
@@ -0,0 +1,62 @@
+
Министерство образования Республики Беларусь
+Учреждение образования
+«Брестский государственный технический университет»
+Кафедра ИИТ
+
+Лабораторная работа №3
+За третий семестр
+По дисциплине: «Общая теория интеллектуальных систем»
+Тема: «Разработка редакторов графов»
+
+Выполнила:
+Студентка 2 курса
+Группы ИИ-23
+Волкогон Н.И.
+
+Проверил:
+Иванюк Д.С.
+
+Брест 2023
+
+--
+# В работе было реализованно: #
+1. Разработка и реализация программного продукта позволяющего
+редактировать графовые конструкции различных видов и производить над
+ними различные действия.
+
+2. Редактор позволяет:
+ a) одновременно работать с несколькими графами (MDI);
+ b) **[\*]** выделение одновременно нескольких элементов графа, копирование
+выделенного фрагмента в clipboard и восстановление из него;
+ c) задавать имена графам;
+ d) сохранять и восстанавливать граф во внутреннем формате программы;
+ e) экспортировать и импортировать граф в текстовый формат (описание
+см. ниже);
+ f) создавать, удалять, именовать, переименовывать, перемещать узлы;
+ g) создавать неориентированные дуги, удалять дуги;
+ h) добавлять, удалять и редактировать содержимое узла (содержимое в
+виде текста и ссылки на файл);
+ i) задавать цвет дуги и узла, образ узла;
+ j) **[\*]** создавать и отображать петли;
+ k) **[\*]** создавать и отображать кратные дуги.
+
+3. Программный продукт позволяет выполнять следующие операции:
+ a) выводить информацию о графе;
+ b) поиск всех путей (маршрутов) между двумя узлами и кратчайших;
+ c) вычисление расстояния между двумя узлами;
+ d) **[\*]** раскраска графа;
+ e) нахождения эйлеровых циклов.
+
+4. Отчет по выполненной лабораторной работе в .md формате (readme.md). Разместить его в следующем каталоге: **trunk\ii0xxyy\task_03\doc** (где **xx** - номер группы, **yy** - номер студента, например **ii02302**).
+
+5. Исходный код разработанной программы разместить в каталоге: **trunk\ii0xxyy\task_03\src**.
+nk\ii0xxyy\task_04\doc.
+
+![Снимок экрана (1)](1.png)
+![Снимок экрана (2)](2.png)
+![Снимок экрана (3)](3.png)
+![Снимок экрана (4)](4.png)
+![Снимок экрана (5)](5.png)
+![Снимок экрана (6)](6.png)
+![Снимок экрана (7)](7.png)
+![Снимок экрана (8)](8.png)
diff --git a/trunk/II02302/task_03/src/CMakeLists.txt b/trunk/II02302/task_03/src/CMakeLists.txt
new file mode 100644
index 000000000..fe78eaf51
--- /dev/null
+++ b/trunk/II02302/task_03/src/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(otis_3)
+
+set(SOURCES
+ Source.cpp
+ library.cpp
+)
+
+set(HEADERS
+ header.h
+)
+
+add_executable(OTIS_03 ${SOURCES} ${HEADERS})
diff --git a/trunk/II02302/task_03/src/Source.cpp b/trunk/II02302/task_03/src/Source.cpp
new file mode 100644
index 000000000..6e59ec3d0
--- /dev/null
+++ b/trunk/II02302/task_03/src/Source.cpp
@@ -0,0 +1,172 @@
+#include
+#include
+#include
+#include "..\Graph_lib\Header.h";
+
+using namespace std;
+
+int main()
+{
+ string str;
+ cout << "Enter file's name: ";
+ cin >> str;
+ ifstream fin(str);
+ int vertexCount, edgesCount;
+ fin >> vertexCount >> edgesCount;
+
+ int** matrix = new int* [vertexCount];
+ for (int i = 0; i < vertexCount; i++)
+ matrix[i] = new int[vertexCount];
+ vector used(vertexCount);
+ int res;
+ int* path = new int[vertexCount];
+ int* f = new int[vertexCount];
+ //menu
+ int go;
+ do
+ {
+ cout << "1. Fill Matrix\n";
+ cout << "2. Paint Matrix\n";
+ cout << "\nlab1\n3. bfs\n";
+ cout << "4. dfs\n";
+ cout << "\nlab2\n5. Gamilton\n";
+ cout << "6. Euler\n";
+ cout << "\nlab3\n7. Dijkstra\n";
+ cout << "8. Floyd\n";
+ cout << "\nlab5\n9. Prim\n";
+ cout << "10.Kruskal\n";
+ cout << "\nlab4\n11. Kali\n";
+ cout << "12. Permutation\n";
+ cout << "\nlab6\n13. Strong connectivity\n";
+ cout << "14.Biconnected Components\n";
+ cout << "0. End\n";
+ cout << "Choise: ";
+ cin >> go;
+ switch (go)
+ {
+ case 1://Fill
+ system("cls");
+ Fill_Matrix(matrix, vertexCount, edgesCount, str);
+ break;
+
+ case 2://Paint
+ system("cls");
+ Paint_Matrix(matrix, vertexCount);
+ break;
+
+ case 3://bfs
+ system("cls");
+ res = 0;
+ for (int i = 0; i < vertexCount; i++)
+ if (!used[i])
+ {
+ res++;
+ bfs(matrix, vertexCount, i, used);
+ }
+ cout << endl << "Number of connectivity components: " << res << endl;
+ break;
+
+ case 4://dfs
+ system("cls");
+ res = 0;
+ for (int i = 0; i < vertexCount; i++)
+ if (!used[i])
+ {
+ res++;
+ dfs(matrix, vertexCount, i, used);
+ }
+ cout << endl << "Number of connectivity components: " << res << endl;
+ break;
+
+ case 5://Gamilton
+ system("cls");
+ int v0;
+ cout << "Enter firts vertex: ";
+ cin >> v0;
+ v0--;
+ for (int i = 0; i < vertexCount; i++)
+ f[i] = -1;
+ f[v0] = v0;
+ path[0] = v0;
+ if (Gamilton(matrix, path, f, vertexCount, 1, v0))
+ {
+ Print_Path(path, vertexCount);
+ cout << endl;
+ }
+ else cout << "No results\n";
+ break;
+
+ case 6://Euler
+ system("cls");
+
+ if ( res > 1)
+ cout << "Wrong\n";
+ else
+ {
+
+ int check = 0;
+ int buf;
+ for (int i = 0; i < vertexCount; i++)
+ {
+ buf = 0;
+ for (int j = 0; j < vertexCount; j++)
+ buf += matrix[i][j];
+ if (buf % 2)
+ check++;
+ }
+ if (check)
+ cout << "Wrong\n";
+ else
+ {
+
+ vectorpath;
+ Euler(matrix, path, vertexCount);
+ for (int i = 1; i < path.size(); i++)
+ cout << path[i] + 1 << " ";
+ cout << endl;
+ break;
+ }
+ }
+
+ case 7:
+ system("cls");
+ Dijkstra(matrix,vertexCount);
+ break;
+
+ case 8:
+ system("cls");
+ Floyd(matrix, vertexCount);
+ break;
+
+ case 9:
+ system("cls");
+ Prim(matrix, vertexCount);
+ break;
+
+ case 10:
+ system("cls");
+ main_kruskal(matrix,vertexCount, edgesCount,str);
+ break;
+
+ case 11:
+ system("cls");
+ Kali();
+ break
+ ;
+ case 12:
+ system("cls");
+ Permutation(str);
+ break;
+
+ case 13:
+ system("cls");
+ StrongConnectedComponents(matrix, vertexCount);
+ break;
+ case 14:
+ system("cls");
+ FindArtPointsAndBridges(matrix, vertexCount);
+ break;
+ }
+ } while (go);
+
+}
diff --git a/trunk/II02302/task_03/src/header.h b/trunk/II02302/task_03/src/header.h
new file mode 100644
index 000000000..65eae5f58
--- /dev/null
+++ b/trunk/II02302/task_03/src/header.h
@@ -0,0 +1,21 @@
+using namespace std;
+#pragma once
+void dfs(int**, int, int, vector&);
+void bfs(int**, int, int, vector&);
+void Fill_Matrix(int**&, int, int, string);
+void Paint_Matrix(int**&, int);
+bool Gamilton(int**&, int*&, int*&, int, int, int);
+void Print_Path(int*&, int);
+void Euler(int**&, vector&, int);
+void Dijkstra(int**&, int);
+void Floyd(int**&, int);
+void Prim(int**&, int);
+int parent(int*, int);
+void union_find(int*, int, int);
+void Kruskal(pair>*, int*, int**&, int, int);
+void main_kruskal(int**&, int, int, string);
+void Kali();
+void Permutation(string);
+void StrongConnectedComponents(int**&, int);
+//void findBiconnectedComponents(int**&, int);
+void FindArtPointsAndBridges(int**&, int);
\ No newline at end of file
diff --git a/trunk/II02302/task_03/src/library.cpp b/trunk/II02302/task_03/src/library.cpp
new file mode 100644
index 000000000..a2257bd9d
--- /dev/null
+++ b/trunk/II02302/task_03/src/library.cpp
@@ -0,0 +1,712 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+const int inf = 10000;
+
+void dfs(int** matrix, int vertexCount, int v, vector& used)//â ãëóáèíó
+{
+ cout << endl;
+ stack stack;
+ stack.push(v);
+ while (!stack.empty())
+ {
+ v = stack.top();
+ stack.pop();
+ if (used[v])
+ continue;
+ used[v] = true;
+ cout << v + 1;
+ for (int i = 0; i < vertexCount; i++)
+ if (!used[i] && matrix[v][i])
+ stack.push(i);
+ }
+}
+
+void bfs(int** matrix, int vertexCount, int v, vector& used)//â øèðèíó
+{
+ cout << endl;
+ queue q;
+ q.push(v);
+ used[v] = true;
+ while (!q.empty())
+ {
+ int u = q.front();
+ q.pop();
+ cout << u + 1 << " ";
+ for (int i = 0; i < vertexCount; i++)
+ {
+ if (!used[i] && matrix[u][i])
+ {
+ q.push(i);
+ used[i] = true;
+ }
+ }
+ }
+}
+
+void Fill_Matrix(int**& matrix, int vertexCount, int edgesCount, string str)
+{
+ ifstream fin(str);
+ for (int i = 0; i < vertexCount; i++)
+ for (int j = 0; j < vertexCount; j++)
+ matrix[i][j] = false;
+ int buf1, buf;
+ fin >> buf >> buf1;
+ for (int i = 0; i < edgesCount; i++)
+ {
+ int a, b, c;
+ fin >> a >> b >> c;
+ cout << a << " -> " << b << endl;
+ a--; b--;
+ matrix[a][b] = c;
+ //matrix[b][a] = c;
+ }
+}
+
+void Paint_Matrix(int**& matrix, int vertexCount)
+{
+ for (int i = 0; i < vertexCount; i++)
+ {
+ for (int j = 0; j < vertexCount; j++)
+ cout << matrix[i][j] << " ";
+ cout << endl;
+ }
+}
+
+void Print_Path(int*& path, int vetexCount)
+{
+ for (int i = 0; i < vetexCount; i++)
+ cout << path[i] + 1 << " ";
+ cout << path[0] + 1;
+}
+
+bool Gamilton(int**& matrix, int*& path,int*& f, int vertexCount, int k, int v0)//íà÷àëüíàÿ âåðøèíà
+{
+ bool res = false;
+ for (int i = 0; i < vertexCount; i++)
+ {
+ if (matrix[i][path[k - 1]])
+ {
+ if (k == vertexCount && i == v0)
+ res = true;
+ else
+ if (f[i] == -1)
+ {
+ f[i] = k;
+ path[k] = i;
+ res = Gamilton(matrix, path, f, vertexCount, k + 1, v0);
+ if (!res) f[i] = -1;
+ }
+ }
+ else continue;
+ }
+ return res;
+}
+
+void Euler(int**& matrix, vector& path, int vertexCount)//íà÷àëüíàÿ âåðøèíà
+{
+ int* degree = new int[vertexCount];
+ for (int i = 0; i < vertexCount; i++)
+ degree[i] = NULL;
+ for (int i = 0; i < vertexCount; i++)
+ for (int j = 0; j < vertexCount; j++)
+ if (matrix[i][j])
+ degree[i]++;
+ stack st;
+ st.push(0);
+ path.push_back(0);
+ while (!st.empty())
+ {
+ int v = st.top();
+ if (degree[v] == NULL)
+ {
+ st.pop();
+ path.push_back(v);
+ }
+ else
+ {
+ for(int i = 0; i < vertexCount ;i++)
+ if (matrix[v][i])
+ {
+ matrix[v][i] = NULL;
+ matrix[i][v] = NULL;
+ degree[v]--;
+ degree[i]--;
+ st.push(i);
+ break;
+ }
+ }
+ }
+}
+
+void Dijkstra(int**& matrix, int vertexCount)
+{
+ for (int i = 0; i < vertexCount; i++)
+ for (int j = 0; j < vertexCount; j++)
+ {
+ if (matrix[i][j] == NULL)
+ matrix[i][j] = inf;
+ }
+ vector dist(vertexCount, inf);
+ vector used(vertexCount, false);
+ vector prev(vertexCount, -1);
+
+ dist[0] = NULL;
+ used[0] = true;
+ prev[0] = NULL;
+
+ for (int i = 0; i < vertexCount; i++)
+ if (matrix[0][i] <= dist[i])
+ {
+ dist[i] = matrix[0][i];
+ prev[i] = NULL;
+ }
+
+ for (int i = 0; i < vertexCount - 1; i++)
+ {
+ int min = inf;
+ for (int j = 0; j < dist.size(); j++)
+ if (min > dist[j] && !used[j])
+ min = j;
+ int minDist = dist[min];
+ used[min] = true;
+
+ for (int j = 0; j < vertexCount; j++)
+ {
+ if (!used[j] && dist[j] > matrix[min][j] + minDist && minDist>0)
+ {
+ dist[j] = matrix[min][j] + minDist;
+ prev[j] = min;
+ }
+ }
+ }
+ for (int i = 0; i < vertexCount; i++) {
+ cout << i + 1 << "\t" << dist[i] << "\t" << prev[i] + 1 << endl;
+ }
+
+}
+
+void Floyd(int**& matrix, int vertexCount)
+{
+
+ int** temp = matrix;
+ for(int i = 0; i < vertexCount; i++)
+ for (int j = 0; j < vertexCount; j++)
+ {
+ if (i == j) temp[i][j] = NULL;
+ else if (matrix[i][j]) temp[i][j] = matrix[i][j];
+ else temp[i][j] = inf;
+ }
+ for (int k = 0; k < vertexCount; k++)
+ for (int i = 0; i < vertexCount; i++)
+ for (int j = 0; j < vertexCount; j++)
+ if (temp[i][j] > temp[i][k] + temp[k][j])
+ temp[i][j] = temp[i][k] + temp[k][j];
+ for (int i = 0; i < vertexCount; i++)
+ {
+ for (int j = 0; j < vertexCount; j++)
+ cout << temp[i][j] << "\t";
+ cout << endl;
+ }
+}
+
+void Prim(int**& matrix,int vertexCount)
+{
+ bool* selected = new bool[vertexCount];
+ for (int i = 0; i < vertexCount; i++)
+ selected[i] = false;
+ selected[0] = true;
+ int search = NULL;
+ int column = 0, line = 0;
+ int weight = NULL;
+ while (search < vertexCount - 1)
+ {
+ int min = inf;
+ for(int i = 0; i < vertexCount; i++)
+ if(selected[i])
+ for(int j = 0; j < vertexCount; j++)
+ if(!selected[j] && matrix[i][j])
+ if (min > matrix[i][j])
+ {
+ min = matrix[i][j];
+ line = i;
+ column = j;
+ }
+ cout << line + 1 << " -> " << column + 1 << " = " << min;
+ search++;
+ weight += min;
+ cout << endl;
+ selected[column] = true;
+ }
+ cout << "Total weight is " << weight << endl;
+}
+
+int parent(int* root, int a)
+{
+ while (root[a] != a)
+ {
+ root[a] = root[root[a]];
+ a = root[a];
+ }
+ return a;
+}
+
+void union_find(int* root, int a, int b)
+{
+ int d = parent(root, a);
+ int e = parent(root, b);
+ root[d] = root[e];
+}
+
+int Kruskal(pair>* p, int* root, int**& matrix, int vertexCount, int edgesCount)
+{
+ int mincost = NULL;
+
+ for (int i = 0; i < edgesCount; i++)
+ {
+ int a = p[i].second.first;
+ int b = p[i].second.second;
+ int cost = p[i].first;
+ if (parent(root, a) != parent(root, b))
+ {
+ mincost += cost;
+ union_find(root, a, b);
+ cout << a + 1 << " -> " << b + 1 << " " << cost << endl;
+ }
+ }
+ return mincost;
+}
+
+void main_kruskal(int**& matrix, int vertexCount, int edgesCount, string str)
+{
+ pair> p[inf];
+ int root[inf];
+ int mincost;
+ for (int i = 0; i < inf; i++)
+ root[i] = i;
+ ifstream fin(str);
+ int buf1, buf2;
+ fin >> buf1 >> buf2;
+ for (int i = 0; i < edgesCount; i++)
+ {
+ int a, b, c;
+ fin >> a >> b >> c;
+ a--; b--;
+ p[i] = make_pair(c, make_pair(a, b));
+ }
+ sort(p, p + edgesCount);
+ mincost = Kruskal(p, root, matrix, vertexCount, edgesCount);
+ cout << mincost << endl;
+}
+
+void f(vector& used, vector& perm, vector>& transposition, int i, int& n)
+{
+ vector res;
+ while (!used[i])
+ {
+ res.push_back(perm[i]);
+ used[i] = true;
+ i = perm[i];
+ }
+ if (!res.empty())
+ {
+ cout << "( ";
+ for (int i = 0; i < res.size() - 1; i++)
+ cout << res[i] + 1 << " , ";
+
+ cout << res.back() + 1 << " )";
+
+ for (int i = 1; i < res.size(); i++)
+ {
+ transposition[n][0] = res[0] + 1;
+ transposition[n][1] = res[i] + 1;
+ n++;
+ }
+ }
+}
+
+void Permutation(string str)
+{
+ vector perm(6);
+ ifstream fin(str);
+ for (int i = 0; i < 6; i++)
+ {
+ fin >> perm[i];
+ perm[i]--;
+ }
+ for (int i = 0; i < 6; i++)
+ cout << i + 1 << " ";
+ cout << endl;
+ for (int i = 0; i < 6; i++)
+ cout << perm[i] + 1 << " ";
+
+ cout << endl;
+ int n = 0;
+ vector> transposition(4,vector (2));
+ vector used(6);
+ for(int i=0; i<6; i++)
+ f(used, perm,transposition, i, n);
+ cout << endl;
+ for (int i = 0; i < transposition.size(); i++)
+ cout <<"{ " << transposition[i][0] << " , " << transposition[i][1] << " } ";
+ cout << endl;
+ cout << "Degree of permutation is " << perm.size() << endl;
+ int perm_degree = 0;
+ for (int i = 0; i < perm.size(); i++)
+ for (int j = i + 1; j < perm.size(); j++)
+ if (perm[i] > perm[j])
+ perm_degree++;
+ cout << "Number of inversions is " << perm_degree << endl;
+ if (perm_degree % 2)
+ cout << "Permutation is odd\n";
+ else cout << "Permutation is even\n";
+
+
+}
+
+void table_kali(vector& mass, int& neutral)
+{
+ for (int i = 0; i < mass.size(); i++)
+ {
+ for (int j = 0; j < mass.size(); j++)
+ cout << (mass[i] * mass[j]) % 7 << "\t";
+ cout << endl;
+ }
+}
+
+void Kali()
+{
+ int neutral = NULL;
+ vector kali(6);
+ for (int i = 0; i < 6; i++)
+ kali[i] = i + 1;
+ for (int i = 0; i < 6; i++)
+ for (int j = 0; j < 6; j++)
+ if (kali[i] * kali[j] % 7 == kali[j])
+ neutral = kali[i];
+ /*for (int i = 0; i < 6; i++)
+ {
+ for (int j = 0; j < 6; j++)
+ {
+ if (kali[i] * kali[j] == kali[j]) buf++;
+ cout << (kali[i] * kali[j]) % 7 << "\t";
+ }
+ if (buf)
+ {
+ neutral = kali[i];
+ buf = -1;
+ }
+ cout << endl;
+ }*/
+
+ table_kali(kali, neutral);
+
+ cout << "Neutral element is " << neutral << endl;
+ cout << "Reverse elements:\n";
+ for (int i = 0; i < 6; i++)
+ for (int j = 0; j < 6; j++)
+ if (kali[i] * kali[j] % 7 == neutral)
+ cout << "for " << kali[i] << " is " << kali[j] << endl;
+
+ vector undergroup;
+
+
+ for (int i = 0; i < 6; i++)
+ {
+ vector group;
+ int p = 0;
+ int res;
+ res = pow(kali[i], 2);
+ res %= 7;
+ group.push_back(res);
+ while (p < 6)
+ {
+ p++;
+ if (res == neutral)
+ {
+ cout << "Degree for " << kali[i] << " is " << p << endl;
+ if (p == 5)
+ cout << "Element " << kali[i] << " generates a cycle group " << endl;
+ else cout << "Element " << kali[i] << " generates a group " << endl;
+ if (i == 1) {
+ undergroup.push_back(kali[i]);
+ cout << "{ " << kali[i] << " , ";
+ for (int i = 0; i < group.size() - 1; i++)
+ {
+ cout << group[i] << " , ";
+ undergroup.push_back(group[i]);
+ }
+ undergroup.push_back(group.back());
+ cout << group.back() << " }" << endl;
+ break;
+ }
+ else
+ {
+ cout << "{ " << kali[i] << " , ";
+ for (int i = 0; i < group.size() - 1; i++)
+ cout << group[i] << " , ";
+ cout << group.back() << " }" << endl;
+ break;
+ }
+ }
+ else
+ {
+ res *= kali[i];
+ res %= 7;
+ group.push_back(res);
+ }
+ }
+ }
+
+ cout << endl;
+ sort(undergroup.begin(), undergroup.end());
+ cout << "Kali's table for H2" << endl;
+ table_kali(undergroup, neutral);
+
+
+}
+
+//void findArticulationPoints(int**& matrix, int vertexCount, int v, int& time, vectorused, vectordisc, vectorlow, stack> st)
+//{
+// disc[v] = low[v] = ++time;
+// used[v] = true;
+//
+// for (int i = 0; i < vertexCount; i++)
+// {
+// if (!matrix[v][i])
+// continue;
+// if (!used[v])
+// {
+// st.push(make_pair(v, i));
+// findArticulationPoints(matrix, vertexCount, i, time, used, disc, low, st);
+// low[v] = min(low[i], low[v]);
+//
+// if (low[i] >= disc[v])
+// {
+// cout << "Íîâàÿ êîìïîíåíòà äâóñâÿçíîñòè: ";
+// while (st.top() != make_pair(v, i))
+// {
+// cout << st.top().first << " -- " << st.top().second << endl;
+// st.pop();
+// }
+// cout << st.top().first << " -- " << st.top().second << endl;
+// st.pop();
+//
+// }
+//
+// }
+// else if (i != st.top().first && disc[i] < low[v])
+// {
+// low[v] = disc[i];
+// st.push(make_pair(v,i));
+// }
+// }
+//}
+//
+//void findBiconnectedComponents(int**& matrix, int vertexCount)
+//{
+// vector used(vertexCount, false);
+// vector disc(vertexCount, false);
+// vector low(vertexCount, false);
+// stack> st;
+// int time = 0;
+//
+// for (int i = 0; i < vertexCount; i++)
+// if (!used[i])
+// findArticulationPoints(matrix, vertexCount, i, time, used, disc, low, st);
+//
+//}
+//
+void transposition(int**& matrix, int vertexcount, vector>& transpon)
+{
+ for (int i = 0; i < vertexcount; i++)
+ for (int j = 0; j < vertexcount; j++)
+ transpon[i][j] = matrix[j][i];
+}
+
+void fillorder(int**& matrix, int vertexcount, int v, vector& visited, stack & st)
+{
+ visited[v] = true;
+ for (int i = 0; i < vertexcount; i++)
+ if (matrix[v][i] && !visited[i])
+ fillorder(matrix, vertexcount, i, visited, st);
+ st.push(v);
+}
+
+void dfs1(int**& matrix, int vertexcount, int v, vector& visited)
+{
+ visited[v] = true;
+ cout << v + 1 << " ";
+ for (int i = 0; i < vertexcount; i++)
+ if (matrix[v][i] && !visited[i])
+ dfs1(matrix, vertexcount, i, visited);
+}
+
+void StrongConnectedComponents(int**& matrix, int vertexcount)
+{
+ stack st;
+ vector visited(vertexcount, false);
+ for (int i = 0; i < vertexcount; i++)
+ if (!visited[i])
+ fillorder(matrix, vertexcount, i, visited, st);
+
+ vector> transpon(vertexcount, vector(vertexcount, false));
+
+ transposition(matrix, vertexcount, transpon);
+
+ visited.assign(vertexcount, false);
+
+ while (!st.empty())
+ {
+ int v = st.top();
+ st.pop();
+
+ if (!visited[v])
+ {
+ dfs1(matrix, vertexcount, v, visited);
+ cout << endl;
+ }
+ }
+}
+
+bool CheckForPath(int**& matrix, int vertexCount, int start, vector& inPath)
+{
+ int check = 0;
+ for (int i = 0; i < vertexCount; i++)
+ if (matrix[start][i] && !inPath[i])
+ check++;
+ if (!check)
+ return false;
+ return true;
+}
+
+void FillStack(int**& matrix, int vertexCount,stack& mainStack)
+{
+ stack tempStack;
+ vector isVisited(vertexCount, false);
+ vector path;
+ vector inPath(vertexCount, false);
+
+ tempStack.push(NULL);
+
+ while (!tempStack.empty())
+ {
+ int top = tempStack.top();
+ path.push_back(top);
+ tempStack.pop();
+ if (!isVisited[top])
+ {
+ isVisited[top] = true;
+ int check = 0;
+ for (int i = 0; i < vertexCount; i++)
+ if (matrix[top][i] && !isVisited[i])
+ {
+ tempStack.push(i);
+ check++;
+ }
+ if (!check)
+ {
+ mainStack.push(top);
+ inPath[top] = true;
+
+ for (int i = 2; i < path.size() + 1; i++)
+ {
+ int start = path[path.size() - i];
+ if (!inPath[start] && !CheckForPath(matrix, vertexCount, start, inPath))
+ {
+ mainStack.push(start);
+ inPath[start] = true;
+ }
+ }
+ }
+ }
+ }
+}
+
+void PrintSSCs(int**& matrix, int vertexCount, stack& mainStack)
+{
+ vector isVisited(vertexCount, false);
+ while (!mainStack.empty())
+ {
+ int top = mainStack.top();
+ mainStack.pop();
+
+ if (!isVisited[top])
+ {
+ isVisited[top] = true;
+ stack tempStack;
+ tempStack.push(top);
+
+ while (!tempStack.empty())
+ {
+ int ttop = tempStack.top();
+ tempStack.pop();
+ for (int i = 0; i < vertexCount; i++)
+ {
+ if (matrix[i][ttop] && !isVisited[i])
+ {
+ tempStack.push(i);
+ isVisited[i] = true;
+ }
+ }
+ }
+ }
+ }
+}
+
+void TarjanDFS(int**& matrix, int vertexCount, int u, vector& disc, vector& low, vector& parent, vector& articulationPoint, vector >& bridge)
+{
+ static int time = 0;
+ disc[u] = low[u] = time;
+ time++;
+ int children = 0;
+
+ for (int v = 0; v < vertexCount; v++)
+ {
+ if (disc[v] == -1 && matrix[u][v])
+ {
+ children++;
+ parent[v] = u;
+ TarjanDFS(matrix, vertexCount, v, disc, low, parent, articulationPoint, bridge);
+ low[u] = min(low[u], low[v]);
+
+ if (parent[u] == -1 and children > 1)
+ articulationPoint[u] = true;
+
+ if (parent[u] != -1 and low[v] >= disc[u])
+ articulationPoint[u] = true;
+
+ if (low[v] > disc[u])
+ bridge.push_back({ u, v });
+ }
+ else if (v != parent[u] && matrix[u][v])
+ low[u] = min(low[u], disc[v]);
+ }
+}
+
+void FindArtPointsAndBridges(int**& matrix, int vertexCount)
+{
+ vector disc(vertexCount, -1), low(vertexCount, -1), parent(vertexCount, -1);
+ vector articulationPoint(vertexCount, false);
+ vector> bridge;
+
+ for (int i = 0; i < vertexCount; i++)
+ if (disc[i] == -1)
+ TarjanDFS(matrix, vertexCount, i, disc, low, parent, articulationPoint, bridge);
+ cout << "Articulation points: ";
+ for (int i = 0; i < vertexCount; i++)
+ if (articulationPoint[i])
+ cout << i + 1 << " ";
+ cout << "\nBridges: ";
+ for(int i=0;i