5#ifdef GRAPH_VISUALIZATION_H
6#include "../../visualization/graph_visual/graph_visualization.h"
18#include <unordered_map>
21#include <unordered_set>
31template <
typename T>
class graph {
40 std::vector<std::pair<T, std::vector<T>>> _adj = {}) {
42 if (_type ==
"directed" || _type ==
"undirected") {
45 throw std::invalid_argument(
"Can't recognize the type of graph");
48 for (
size_t i = 0; i < _adj.size(); i++) {
49 for (T &neigh : _adj[i].second) {
50 this->
add_edge(_adj[i].first, neigh);
54 }
catch (std::invalid_argument &e) {
55 std::cerr << e.what() <<
'\n';
65 graph(
const graph &g) : adj(g.adj), _elements(g._elements), _type(g._type) {
76 _elements = g._elements;
92 if (_type ==
"undirected") {
110 if (_elements.find(start) == _elements.end()) {
113 for (T &x : adj[start]) {
134 bool empty() {
return _elements.empty(); }
147 std::vector<T>
dfs(T start);
154 std::vector<T>
bfs(T start);
186 std::vector<std::vector<T>>
bridge(T start);
222 for (T &x : elements) {
235 std::unordered_map<T, std::vector<T>> adj;
236 std::unordered_set<T> _elements;
242 void dfs_bridge(T start, T parent, int64_t &time,
243 std::unordered_map<T, bool> &visited,
244 std::unordered_map<T, int64_t> &in,
245 std::unordered_map<T, int64_t> &out,
246 std::vector<std::vector<T>> &bridges) {
247 visited[start] =
true;
248 in[start] = out[start] = time++;
249 for (T &x : adj[start]) {
251 if (visited.find(x) == visited.end()) {
252 dfs_bridge(x, start, time, visited, in, out, bridges);
253 if (out[x] > in[start]) {
254 bridges.push_back({x, start});
257 out[start] = std::min(out[start], out[x]);
265 void dfs_scc(T start, std::unordered_map<T, bool> &visited, std::stack<T> &s) {
266 visited[start] =
true;
267 for(
auto & x : adj[start]) {
268 if(visited.find(x) == visited.end()) {
269 dfs_scc(x, visited, s);
281 if (this->empty() || _elements.find(start) == _elements.end()) {
285 std::unordered_map<T, bool> visited;
287 visited[start] =
true;
290 path.push_back(current);
292 for (T &x : adj[current]) {
293 if (visited.find(x) == visited.end()) {
304 if (this->empty() || _elements.find(start) == _elements.end()) {
308 std::unordered_map<T, bool> visited;
310 visited[start] =
true;
312 int64_t size = q.size();
313 for (int64_t i = 0; i < size; i++) {
314 T current = q.front();
315 path.push_back(current);
317 for (T &x : adj[current]) {
318 if (visited.find(x) == visited.end()) {
329 auto explore = [&](std::unordered_map<T, bool> &visited, T element) ->
void {
332 visited[element] =
true;
334 T current = q.front();
336 for (T &x : adj[current]) {
337 if (visited.find(x) == visited.end()) {
344 size_t n = _elements.size();
346 std::unordered_map<T, bool> visited;
347 for (T x : _elements) {
348 if (visited.find(x) == visited.end()) {
357 std::unordered_map<T, int> indeg;
361 for (T x : _elements) {
362 for (T &y : adj[x]) {
367 for (T x : _elements) {
374 T current = q.front();
377 for (T &x : adj[current]) {
378 if (--indeg[x] == 0) {
387 std::vector<T> top_sort;
388 std::unordered_map<T, bool> visited;
389 std::unordered_map<T, int64_t> indeg;
390 for (T x : _elements) {
391 for (T &y : adj[x]) {
397 for (T x : _elements) {
405 T current = q.front();
407 top_sort.push_back(current);
408 for (T &x : adj[current]) {
409 if (visited.find(x) == visited.end()) {
410 if (--indeg[x] == 0) {
422 std::unordered_map<T, int> color;
423 std::queue<std::pair<T, int>> q;
425 for (T x : _elements) {
426 if (color.find(x) == color.end()) {
430 std::pair<T, int> current = q.front();
433 int col = current.second;
434 for (T &x : adj[v]) {
435 if (color.find(x) != color.end() && color[x] == col) {
438 if (color.find(x) == color.end()) {
439 color[x] = (col) ? 0 : 1;
440 q.push({x, color[x]});
451 std::vector<std::vector<T>> bridges;
452 std::unordered_map<T, bool> visited;
453 std::unordered_map<T, int64_t> in, out;
454 for (T x : _elements) {
458 dfs_bridge(start, -1, timer, visited, in, out, bridges);
463 std::unordered_map<T, bool> visited;
466 for (
auto &ele : adj) {
467 if (adj[ele.first].size() != 0) {
478 visited[start] =
true;
482 for (T &x : adj[current]) {
483 if (visited.find(x) == visited.end()) {
490 for (T x : _elements) {
491 if (visited.find(x) == visited.end() && adj[x].size() > 0) {
499 if (
this -> size() == 0) {
503 std::unordered_map<T, bool> visited;
506 for(
const T& x: _elements) {
507 if(visited.find(x) == visited.end()) {
508 dfs_scc(x, visited, s);
512 std::unordered_map<T, std::vector<T> > new_adj;
513 for(
const T& x: _elements) {
514 for(
const auto& neigh: adj[x]) {
515 new_adj[neigh].push_back(x);
522 auto dfs_new = [&](T start) ->
void {
525 visited[start] =
true;
527 T current = _s.top();
529 for(
auto & x: new_adj[current]) {
530 if (visited.find(x) == visited.end()) {
541 if (visited.find(current) == visited.end()) {
551 if (this->connected() ==
false) {
556 for (
auto &el : adj) {
557 if (adj[el.first].size() & 1) {
565 return (odd) ? 1 : 2;
568#ifdef GRAPH_VISUALIZATION_H
571 if (_type ==
"directed") {
572 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
573 for (
auto &[element, neighbors] : adj) {
574 for (T &x : neighbors) {
582 for (
auto &[element, neighbors] : adj) {
583 for (T &x : neighbors) {
584 s += std::to_string(element);
586 s += std::to_string(x);
592 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
593 for (
auto &[element, neighbors] : adj) {
594 for (T &x : neighbors) {
602 for (
auto &[element, neighbors] : adj) {
603 for (T &x : neighbors) {
604 s += std::to_string(element);
606 s += std::to_string(x);
613 if (_type ==
"directed") {
614 digraph_visualization::visualize(s);
616 graph_visualization::visualize(s);
633 std::vector<std::pair<std::pair<T, T>, int64_t>> _adj = {}) {
635 if (_type ==
"directed" || _type ==
"undirected") {
638 throw std::invalid_argument(
"Can't recognize the type of graph");
641 for (
size_t i = 0; i < _adj.size(); i++) {
642 this->
add_edge(_adj[i].first.first, _adj[i].first.second,
646 }
catch (std::invalid_argument &e) {
647 std::cerr << e.what() <<
'\n';
669 _elements = g._elements;
687 if (_type ==
"undirected") {
688 adj[u].push_back(std::make_pair(v, w));
689 adj[v].push_back(std::make_pair(u, w));
690 }
else if (_type ==
"directed") {
691 adj[u].push_back(std::make_pair(v, w));
704 if (_elements.find(start) == _elements.end()) {
707 for (std::pair<T, double> &x : adj[start]) {
708 if (x.first == end) {
727 bool empty() {
return _elements.empty(); }
740 std::vector<T>
dfs(T start);
747 std::vector<T>
bfs(T start);
780 int64_t
prim(T start);
793 std::vector<std::vector<T>>
bridge(T start);
843 for (T &x : elements) {
856 std::unordered_map<T, std::vector<std::pair<T, double>>> adj;
858 std::unordered_set<T> _elements;
863 void dfs_bridge(T start, T parent, int64_t &time,
864 std::unordered_map<T, bool> &visited,
865 std::unordered_map<T, int64_t> &in,
866 std::unordered_map<T, int64_t> &out,
867 std::vector<std::vector<T>> &bridges) {
868 visited[start] =
true;
869 in[start] = out[start] = time++;
870 for (std::pair<T, double> &x : adj[start]) {
871 if (x.first != parent) {
872 if (visited.find(x.first) == visited.end()) {
873 dfs_bridge(x.first, start, time, visited, in, out, bridges);
874 if (out[x.first] > in[start]) {
875 bridges.push_back({x.first, start});
878 out[start] = std::min(out[start], out[x.first]);
886 void dfs_scc(T start, std::unordered_map<T, bool> &visited, std::stack<T> &s) {
887 visited[start] =
true;
888 for(
auto & x : adj[start]) {
889 if(visited.find(x.first) == visited.end()) {
890 dfs_scc(x.first, visited, s);
899 return _elements.size();
903 if (_elements.find(start) == _elements.end()) {
904 std::cout <<
"Element: " << start <<
" is not found in the Graph" <<
'\n';
907 if (_elements.find(end) == _elements.end()) {
908 std::cout <<
"Element: " << end <<
" is not found in the Graph" <<
'\n';
912 if (!cycle() && _type ==
"directed") {
913 std::vector<T> top_sort = topological_sort();
914 std::reverse(top_sort.begin(), top_sort.end());
916 std::unordered_map<T, double> dist;
917 for (
auto &x : _elements) {
918 dist[x] = std::numeric_limits<int64_t>::max();
921 while (!top_sort.empty()) {
922 auto current = top_sort.back();
924 if (dist[current] != std::numeric_limits<int64_t>::max()) {
925 for (std::pair<T, double> &x : adj[current]) {
926 if (dist[x.first] > dist[current] + x.second) {
927 dist[x.first] = dist[current] + x.second;
928 top_sort.push_back(x.first);
933 return (dist[end] != std::numeric_limits<int64_t>::max()) ? dist[end] : -1;
935 std::unordered_map<T, double> dist;
936 for (
auto &x : _elements) {
937 dist[x] = std::numeric_limits<int64_t>::max();
939 std::priority_queue<std::pair<double, T>,
940 std::vector<std::pair<double, T>>,
941 std::greater<std::pair<double, T>>>
943 pq.push(std::make_pair(0, start));
945 while (!pq.empty()) {
946 T currentNode = pq.top().second;
947 double currentDist = pq.top().first;
949 for (std::pair<T, double> &edge : adj[currentNode]) {
950 if (currentDist + edge.second < dist[edge.first]) {
951 dist[edge.first] = currentDist + edge.second;
952 pq.push(std::make_pair(dist[edge.first], edge.first));
956 return (dist[end] != std::numeric_limits<int64_t>::max()) ? dist[end] : -1;
964 if (this->empty() || _elements.find(start) == _elements.end()) {
968 std::unordered_map<T, bool> visited;
970 visited[start] =
true;
972 int64_t size = s.size();
973 for (int64_t i = 0; i < size; i++) {
975 path.push_back(current);
977 for (std::pair<T, double> &x : adj[current]) {
978 if (visited.find(x.first) == visited.end()) {
980 visited[x.first] =
true;
990 if (this->empty() || _elements.find(start) == _elements.end()) {
994 std::unordered_map<T, bool> visited;
996 visited[start] =
true;
998 int64_t size = q.size();
999 for (int64_t i = 0; i < size; i++) {
1000 T current = q.front();
1001 path.push_back(current);
1003 for (std::pair<T, double> &x : adj[current]) {
1004 if (visited.find(x.first) == visited.end()) {
1006 visited[x.first] =
true;
1015 auto explore = [&](std::unordered_map<T, bool> &visited, T element) ->
void {
1018 visited[element] =
true;
1019 while (!s.empty()) {
1020 T current = s.top();
1022 for (std::pair<T, double> &x : adj[current]) {
1023 if (visited.find(x.first) == visited.end()) {
1025 visited[x.first] =
true;
1030 size_t n = _elements.size();
1032 std::unordered_map<T, bool> visited;
1033 for (T x : _elements) {
1034 if (visited.find(x) == visited.end()) {
1035 explore(visited, x);
1043 std::unordered_map<T, int> indeg;
1047 for (T x : _elements) {
1048 for (std::pair<T, double> &y : adj[x]) {
1053 for (T x : _elements) {
1054 if (indeg[x] == 0) {
1059 while (!q.empty()) {
1060 T current = q.front();
1063 for (std::pair<T, double> &x : adj[current]) {
1064 if (--indeg[x.first] == 0) {
1069 return visited == 0;
1073 std::vector<T> top_sort;
1074 std::unordered_map<T, bool> visited;
1075 std::unordered_map<T, int64_t> indeg;
1076 for (T x : _elements) {
1077 for (std::pair<T, double> &y : adj[x]) {
1083 for (T x : _elements) {
1084 if (indeg[x] == 0) {
1090 while (!q.empty()) {
1091 T current = q.front();
1093 top_sort.push_back(current);
1094 for (std::pair<T, double> &x : adj[current]) {
1095 if (visited.find(x.first) == visited.end()) {
1096 if (--indeg[x.first] == 0) {
1098 visited[x.first] =
true;
1108 std::priority_queue<std::pair<T, int64_t>, std::vector<std::pair<T, int64_t>>,
1109 std::greater<std::pair<T, int64_t>>>
1111 std::unordered_map<T, bool> visited;
1113 q.push(std::make_pair(0, _temp));
1114 while (!q.empty()) {
1115 std::pair<T, int64_t> current = q.top();
1117 _temp = current.first;
1118 if (visited.find(_temp) != visited.end()) {
1121 cost += current.second;
1122 visited[_temp] =
true;
1123 for (std::pair<T, double> &x : adj[current.first]) {
1124 if (visited.find(x.first) == visited.end()) {
1133 std::unordered_map<T, int> color;
1134 std::queue<std::pair<T, int>> q;
1136 for (T x : _elements) {
1137 if (color.find(x) == color.end()) {
1140 while (!q.empty()) {
1141 std::pair<T, int> current = q.front();
1143 T v = current.first;
1144 int col = current.second;
1145 for (std::pair<T, double> &x : adj[v]) {
1146 if (color.find(x.first) != color.end() && color[x.first] == col) {
1149 if (color.find(x.first) == color.end()) {
1150 color[x.first] = (col) ? 0 : 1;
1151 q.push({x.first, color[x.first]});
1160template <
typename T>
1163 std::vector<std::vector<T>> bridges;
1164 std::unordered_map<T, bool> visited;
1165 std::unordered_map<T, int64_t> in, out;
1166 for (T x : _elements) {
1170 dfs_bridge(start, -1, timer, visited, in, out, bridges);
1174template <
typename T>
1176 if (
this -> size() == 0) {
1180 std::unordered_map<T, bool> visited;
1183 for(
const T& x : _elements) {
1184 if(visited.find(x) == visited.end()) {
1185 dfs_scc(x, visited, s);
1189 std::unordered_map<T, std::vector<T> > new_adj;
1190 for(
const T& x: _elements) {
1191 for(
const auto& neigh: adj[x]) {
1192 new_adj[neigh.first].push_back(x);
1199 auto dfs_new = [&](T start) ->
void {
1202 visited[start] =
true;
1203 while(!_s.empty()) {
1204 T current = _s.top();
1206 for(
auto & x: new_adj[current]) {
1207 if (visited.find(x) == visited.end()) {
1216 T current = s.top();
1218 if (visited.find(current) == visited.end()) {
1228 std::unordered_map<T, bool> visited;
1231 for (
auto &ele : adj) {
1232 if (adj[ele.first].size() != 0) {
1243 visited[start] =
true;
1244 while (!s.empty()) {
1245 T current = s.top();
1247 for (std::pair<T, double> &x : adj[current]) {
1248 if (visited.find(x.first) == visited.end()) {
1249 visited[x.first] =
true;
1255 for (T x : _elements) {
1256 if (visited.find(x) == visited.end() && adj[x].size() > 0) {
1264 if (this->connected() ==
false) {
1269 for (
auto &el : adj) {
1270 if (adj[el.first].size() & 1) {
1279 return (odd) ? 1 : 2;
1282template <
typename T>
1284 std::unordered_map<T, double> dist;
1287 for (
auto it : adj) {
1288 dist[it.first] = std::numeric_limits<double>::infinity();
1296 for (
int i = 0; i < v - 1; i++) {
1297 for (
const auto j : adj) {
1298 for (
const auto edge : adj[j.first]) {
1299 if (dist[j.first] + edge.second < dist[edge.first]) {
1300 dist[edge.first] = dist[j.first] + edge.second;
1309 for(
int i = 0; i < v - 1; i++) {
1310 for (
const auto j : adj) {
1311 for (
const auto edge : adj[j.first]) {
1312 if (dist[j.first] + edge.second < dist[edge.first]) {
1313 dist[edge.first] = -std::numeric_limits<double>::infinity();
1323#ifdef GRAPH_VISUALIZATION_H
1326 if (_type ==
"directed") {
1327 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
1328 for (
auto &[element, neighbors] : adj) {
1329 for (std::pair<T, double> &x : neighbors) {
1330 if (x.first == element) {
1337 s += std::to_string(x.second);
1343 for (
auto &[element, neighbors] : adj) {
1344 for (std::pair<T, double> &x : neighbors) {
1345 if (x.first == element) {
1348 s += std::to_string(element);
1350 s += std::to_string(x.first);
1352 s += std::to_string(x.second);
1359 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
1360 for (
auto &[element, neighbors] : adj) {
1361 for (std::pair<T, double> &x : neighbors) {
1362 if (x.first == element) {
1369 s += std::to_string(x.second);
1375 for (
auto &[element, neighbors] : adj) {
1376 for (std::pair<T, double> &x : neighbors) {
1377 if (x.first == element) {
1380 s += std::to_string(element);
1382 s += std::to_string(x.first);
1384 s += std::to_string(x.second);
1391 if (_type ==
"directed") {
1392 digraph_visualization::visualize(s);
1394 graph_visualization::visualize(s);
Class for Unweighted Graph.
Definition graph.h:31
int64_t scc()
scc(strongly connected components) function.
Definition graph.h:498
friend std::ostream & operator<<(std::ostream &out, graph< T > &g)
operator << for the graph class.
Definition graph.h:218
bool bipartite()
bipartite function.
Definition graph.h:421
void add_edge(T u, T v)
add_edge function
Definition graph.h:91
std::vector< T > bfs(T start)
bfs function
Definition graph.h:302
std::vector< std::vector< T > > bridge(T start)
bridge function.
Definition graph.h:449
bool has_edge(T start, T end)
has_edge function.
Definition graph.h:109
std::vector< T > dfs(T start)
dfs function
Definition graph.h:279
std::vector< T > topological_sort()
topological_sort function.
Definition graph.h:386
bool cycle()
cycle function.
Definition graph.h:356
void visualize()
visualize function.
void clear()
clear function Clearing the entire graph.
Definition graph.h:125
~graph()
Destroy the graph object.
Definition graph.h:84
bool connected()
connected function.
Definition graph.h:462
graph(std::string _type, std::vector< std::pair< T, std::vector< T > > > _adj={})
Constructor for the unweighted graph.
Definition graph.h:39
size_t size()
size function
Definition graph.h:277
int64_t connected_components()
connected_components function.
Definition graph.h:328
graph(const graph &g)
Construct a new graph object.
Definition graph.h:65
int eulerian()
eulerian function.
Definition graph.h:550
graph & operator=(const graph &g)
operator = for the graph class
Definition graph.h:74
bool empty()
empty function Checks if a graph is empty.
Definition graph.h:134
class for weighted graph
Definition graph.h:624
int eulerian()
eulerian function.
Definition graph.h:1263
int64_t scc()
scc(strongly connected components) function.
Definition graph.h:1175
double shortest_path(T start, T end)
shortest_path function.
Definition graph.h:902
int64_t connected_components()
connected_components function.
Definition graph.h:1014
~weighted_graph()
Destroy the weighted graph object.
Definition graph.h:678
bool bipartite()
bipartite function.
Definition graph.h:1132
std::vector< std::vector< T > > bridge(T start)
bridge function.
Definition graph.h:1161
bool has_edge(T start, T end)
has_edge function.
Definition graph.h:703
weighted_graph(const weighted_graph &g)
Copy constructor for weighted graph class.
Definition graph.h:656
bool cycle()
cycle function.
Definition graph.h:1042
std::vector< T > topological_sort()
topological sort function.
Definition graph.h:1072
std::vector< T > bfs(T start)
bfs function.
Definition graph.h:988
bool empty()
empty function.
Definition graph.h:727
bool connected()
connected function.
Definition graph.h:1227
void visualize()
visualize function.
std::unordered_map< T, double > bellman_ford(T start)
find SSSP and identify negative cycles.
Definition graph.h:1283
std::vector< T > dfs(T start)
dfs function.
Definition graph.h:961
void add_edge(T u, T v, int64_t w)
add_edge function.
Definition graph.h:686
size_t size()
size function.
Definition graph.h:898
int max_flow(T start, T end)
maximum flow function
weighted_graph(std::string _type, std::vector< std::pair< std::pair< T, T >, int64_t > > _adj={})
Constructor for weighted graph.
Definition graph.h:632
void clear()
clear function. Clearing the entire graph.
Definition graph.h:719
weighted_graph & operator=(const weighted_graph &g)
operator = for weighted graph class
Definition graph.h:667
int64_t prim(T start)
prim function.
Definition graph.h:1107
friend std::ostream & operator<<(std::ostream &out, weighted_graph< T > &g)
<< operator for the weighted graph class.
Definition graph.h:840