Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pronin Arkadiy's Tasks #29

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
197 changes: 197 additions & 0 deletions lib/src/graph.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#include "graph.hpp"

#include <iostream>
#include <stdexcept>

#define UNREACHABLE (-1)
EchoPr marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: macro 'UNREACHABLE' defines an integral constant; prefer an enum instead [cppcoreguidelines-macro-to-enum]

#define UNREACHABLE (-1)
        ^


EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: replace macro with enum [cppcoreguidelines-macro-to-enum]

Suggested change
enum {
UNREACHABLE = (-1)};

using namespace algo;

Graph::Graph(int v, int e) {
if (v <= 0)
throw std::invalid_argument(
"Number of vertices must be greater than zero.");

vertexes_num = v;
edges_num = e;
adjList.resize(v);
}

Graph::Graph(int v, int e, bool directed) {
if (v <= 0)
throw std::invalid_argument(
"Number of vertices must be greater than zero.");

vertexes_num = v;
edges_num = e;
is_directed = directed;
adjList.resize(v);
}

void Graph::AddEdge(int u, int v, int weight) {
if (u < 1 || u > vertexes_num || v < 1 || v > vertexes_num) {
throw std::out_of_range("Vertex out of bounds in addEdge.");
}

adjList[u - 1].emplace_back(v - 1, weight);
if (!is_directed) adjList[v - 1].emplace_back(u - 1, weight);

edges_num++;
}

int Graph::GetVertexesNum() {
if (vertexes_num <= 0)
throw std::runtime_error("Graph is not properly initialized.");
return vertexes_num;
}

int Graph::GetEdgesNum() { return edges_num; }

const AdjacencyList Graph::GetAdjList() { return adjList; }

void Graph::PrintGraph() const {
if (vertexes_num == 0) {
std::cerr << "Error: Graph is empty." << std::endl;
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use 'std::endl' with streams; use '\n' instead [performance-avoid-endl]

Suggested change
std::cerr << "Error: Graph is empty." << std::endl;
std::cerr << "Error: Graph is empty." << '\n';

return;
}

for (int i = 0; i < vertexes_num; i++) {
if (adjList[i].empty()) continue;

std::cout << "Node " << i + 1 << ": ";

for (const auto& [neighbor, weight] : adjList[i]) {
std::cout << "(" << neighbor + 1 << ", " << weight << ") ";
}
std::cout << '\n';
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
}
}

std::vector<std::pair<int, int>> Graph::GetNeighbours(int v) {
if (v < 0 || v >= vertexes_num) {
throw std::out_of_range("Vertex index out of bounds in getNeighbours.");
}
return adjList[v];
}

void Graph::TopSort(int v, std::vector<bool>& visited, std::vector<int>& way) {
if (visited[v]) return;
visited[v] = true;
way.push_back(v);

for (auto [u, w] : GetNeighbours(v)) {
if (!visited[u]) {
TopSort(u, visited, way);
}
}
}

std::vector<int> Graph::TopologicalSort(int start) {
if (vertexes_num == 0) {
std::cerr
<< "Error: Graph is empty, topological sort cannot be performed.\n";
return {};
}

std::vector<int> way;
std::vector<bool> visited(GetVertexesNum(), false);

TopSort(start, visited, way);

if (way.size() < vertexes_num)
throw std::invalid_argument("Graph is disconnected.");

return way;
}

std::vector<std::pair<int, int>> Graph::GetBridges() {
std::vector<int> tin(vertexes_num, -1);
std::vector<int> low(vertexes_num, -1);
std::vector<bool> visited(vertexes_num, false);
std::vector<std::pair<int, int>> bridges;
int timer = 0;

for (int i = 0; i < vertexes_num; i++) {
if (!visited[i]) {
DfsBridges(i, -1, tin, low, visited, timer, bridges);
}
}

return bridges;
}

void Graph::DfsBridges(int v, int parent, std::vector<int>& tin,
std::vector<int>& low, std::vector<bool>& visited,
int& timer, std::vector<std::pair<int, int>>& bridges) {
visited[v] = true;
tin[v] = low[v] = timer++;

for (auto [u, _] : adjList[v]) {
if (u == parent) continue;

if (!visited[u]) {
DfsBridges(u, v, tin, low, visited, timer, bridges);
low[v] = std::min(low[v], low[u]);

if (low[u] > tin[v]) {
bridges.emplace_back(v + 1, u + 1); // Добавляем мост (нумерация с 1)
}
} else {
low[v] = std::min(low[v], tin[u]);
}
}
}

std::vector<int> Graph::GetArticulationPoints() {
std::vector<int> tin(vertexes_num, -1);
std::vector<int> low(vertexes_num, -1);
std::vector<bool> visited(vertexes_num, false);
std::vector<bool> isArticulationPoint(vertexes_num, false);
int timer = 0;

for (int i = 0; i < vertexes_num; i++) {
if (!visited[i]) {
DfsArticulation(i, -1, tin, low, visited, timer, isArticulationPoint);
}
}

std::vector<int> articulationPoints;
for (int i = 0; i < vertexes_num; i++) {
if (isArticulationPoint[i]) {
articulationPoints.push_back(i + 1); // Нумерация с 1
}
}

return articulationPoints;
}

void Graph::DfsArticulation(int v, int parent, std::vector<int>& tin,
std::vector<int>& low, std::vector<bool>& visited,
int& timer,
std::vector<bool>& isArticulationPoint) {
visited[v] = true;
tin[v] = low[v] = timer++;
int children = 0;

for (auto [u, _] : adjList[v]) {
if (u == parent) continue;

if (!visited[u]) {
children++;
DfsArticulation(u, v, tin, low, visited, timer, isArticulationPoint);
low[v] = std::min(low[v], low[u]);

// Условие для точки сочленения
if (parent != -1 && low[u] >= tin[v]) {
isArticulationPoint[v] = true;
}
} else {
low[v] = std::min(low[v], tin[u]);
}
}

// Отдельное условие для корня
if (parent == -1 && children > 1) {
isArticulationPoint[v] = true;
}
}
51 changes: 51 additions & 0 deletions lib/src/graph.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#ifndef GRAPH_HPP
#define GRAPH_HPP

#include <vector>

using AdjacencyList = std::vector<std::vector<std::pair<int, int>>>;

namespace algo {
class Graph {
public:
Graph(int v, int e);

Graph(int v, int e, bool directed);

void AddEdge(int, int, int);

int GetVertexesNum();
int GetEdgesNum();
const AdjacencyList GetAdjList();

std::vector<std::pair<int, int>> GetNeighbours(int);

bool HasEdge(int, int) const;

void PrintGraph() const;

std::vector<int> TopologicalSort(int);

std::vector<std::pair<int, int>> GetBridges();
std::vector<int> GetArticulationPoints();

private:
int vertexes_num = 0;
int edges_num = 0;
bool is_directed = false;

AdjacencyList adjList;

void TopSort(int, std::vector<bool>&, std::vector<int>&);

void DfsBridges(int, int, std::vector<int>&, std::vector<int>&,
std::vector<bool>&, int&, std::vector<std::pair<int, int>>&);

void DfsArticulation(int, int, std::vector<int>&, std::vector<int>&,
std::vector<bool>&, int&, std::vector<bool>&);
};
}; // namespace algo

#endif // GRAPH_HPP
43 changes: 43 additions & 0 deletions lib/src/util.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,44 @@
#include "util.hpp"

#include <climits>
#include <queue>
#include <utility>
#include <vector>

#include "graph.hpp"

using namespace std;

vector<int> FindWays(algo::Graph graph, int start) {
vector<int> vis(graph.GetVertexesNum());
vector<int> dst(graph.GetVertexesNum(), INT_MAX);

dst[start - 1] = 0;

Dijkstra(start - 1, -1, vis, dst, graph.GetAdjList());

return dst;
}

void Dijkstra(int v, int from, vector<int>& vis, vector<int>& dst,
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'from' is unused [misc-unused-parameters]

Suggested change
void Dijkstra(int v, int from, vector<int>& vis, vector<int>& dst,
void Dijkstra(int v, int /*from*/, vector<int>& vis, vector<int>& dst,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'vis' is unused [misc-unused-parameters]

Suggested change
void Dijkstra(int v, int from, vector<int>& vis, vector<int>& dst,
void Dijkstra(int v, int from, vector<int>& /*vis*/, vector<int>& dst,

const AdjacencyList adj) {
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved
EchoPr marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: the const qualified parameter 'adj' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param]

lib/src/util.hpp:9:

-               const AdjacencyList);
+               const AdjacencyList&);
Suggested change
const AdjacencyList adj) {
const AdjacencyList& adj) {

using Pair = pair<int, int>;

priority_queue<Pair, vector<Pair>, greater<Pair>> q;

q.push({0, v});
while (!q.empty()) {
auto [cur_d, v] = q.top();
q.pop();

if (cur_d > dst[v]) continue;

for (auto [u, w] : adj[v]) {
if (dst[u] > dst[v] + w) {
dst[u] = dst[v] + w;

q.push({dst[u], u});
}
}
}
}
10 changes: 10 additions & 0 deletions lib/src/util.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <vector>

#include "graph.hpp"

std::vector<int> FindWays(algo::Graph, int);

void Dijkstra(int, int, std::vector<int>&, std::vector<int>&,
const AdjacencyList);
26 changes: 25 additions & 1 deletion task_01/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,25 @@
int main() { return 0; }
#include <iostream>

#include "graph.hpp"

EchoPr marked this conversation as resolved.
Show resolved Hide resolved
int main() {
int vertexes_num, edges_num;
std::cin >> vertexes_num >> edges_num;

algo::Graph graph(vertexes_num, edges_num);

for (int i = 0; i < edges_num; i++) {
int a, b, w;

std::cin >> a >> b >> w;

graph.AddEdge(a, b, w);
}

std::cout << "Topsort:" << std::endl;
for (auto i : graph.TopologicalSort(0)) {
std::cout << i + 1 << " ";
}

std::cout << std::endl;
}
Loading
Loading