4 #ifdef GRAPH_VISUALIZATION_H
5 #include "../../visualization/graph_visual/graph_visualization.h"
16 #include <type_traits>
17 #include <unordered_map>
18 #include <unordered_set>
27 template <
typename T>
class graph {
36 std::vector<std::pair<T, std::vector<T>>> _adj = {}) {
38 if (_type ==
"directed" || _type ==
"undirected") {
41 throw std::invalid_argument(
"Can't recognize the type of graph");
44 for (
size_t i = 0; i < _adj.size(); i++) {
45 for (T &neigh : _adj[i].second) {
46 this->
add_edge(_adj[i].first, neigh);
50 }
catch (std::invalid_argument &e) {
51 std::cerr << e.what() <<
'\n';
61 graph(
const graph &g) : adj(g.adj), _elements(g._elements), _type(g._type) {
72 _elements = g._elements;
88 if (_type ==
"undirected") {
106 if (_elements.find(start) == _elements.end()) {
109 for (T &x : adj[start]) {
130 bool empty() {
return _elements.empty(); }
143 std::vector<T>
dfs(T start);
150 std::vector<T>
bfs(T start);
182 std::vector<std::vector<T>>
bridge(T start);
218 for (T &x : elements) {
231 std::unordered_map<T, std::vector<T>> adj;
232 std::unordered_set<T> _elements;
238 void dfs_bridge(T start, T parent, int64_t &time,
239 std::unordered_map<T, bool> &visited,
240 std::unordered_map<T, int64_t> &in,
241 std::unordered_map<T, int64_t> &out,
242 std::vector<std::vector<T>> &bridges) {
243 visited[start] =
true;
244 in[start] = out[start] = time++;
245 for (T &x : adj[start]) {
247 if (visited.find(x) == visited.end()) {
248 dfs_bridge(x, start, time, visited, in, out, bridges);
249 if (out[x] > in[start]) {
250 bridges.push_back({x, start});
253 out[start] = std::min(out[start], out[x]);
263 if (this->empty() || _elements.find(start) == _elements.end()) {
267 std::unordered_map<T, bool> visited;
269 visited[start] =
true;
272 path.push_back(current);
274 for (T &x : adj[current]) {
275 if (visited.find(x) == visited.end()) {
286 if (this->empty() || _elements.find(start) == _elements.end()) {
290 std::unordered_map<T, bool> visited;
292 visited[start] =
true;
294 int64_t size = q.size();
295 for (int64_t i = 0; i < size; i++) {
296 T current = q.front();
297 path.push_back(current);
299 for (T &x : adj[current]) {
300 if (visited.find(x) == visited.end()) {
311 auto explore = [&](std::unordered_map<T, bool> &visited, T element) ->
void {
314 visited[element] =
true;
316 T current = q.front();
318 for (T &x : adj[current]) {
319 if (visited.find(x) == visited.end()) {
326 size_t n = _elements.size();
328 std::unordered_map<T, bool> visited;
329 for (T x : _elements) {
330 if (visited.find(x) == visited.end()) {
339 std::unordered_map<T, int> indeg;
343 for (T x : _elements) {
344 for (T &y : adj[x]) {
349 for (T x : _elements) {
356 T current = q.front();
359 for (T &x : adj[current]) {
360 if (--indeg[x] == 0) {
369 std::vector<T> top_sort;
370 std::unordered_map<T, bool> visited;
371 std::unordered_map<T, int64_t> indeg;
372 for (T x : _elements) {
373 for (T &y : adj[x]) {
379 for (T x : _elements) {
387 T current = q.front();
389 top_sort.push_back(current);
390 for (T &x : adj[current]) {
391 if (visited.find(x) == visited.end()) {
392 if (--indeg[x] == 0) {
404 std::unordered_map<T, int> color;
405 std::queue<std::pair<T, int>> q;
407 for (T x : _elements) {
408 if (color.find(x) == color.end()) {
412 std::pair<T, int> current = q.front();
415 int col = current.second;
416 for (T &x : adj[v]) {
417 if (color.find(x) != color.end() && color[x] == col) {
420 if (color.find(x) == color.end()) {
421 color[x] = (col) ? 0 : 1;
422 q.push({x, color[x]});
433 std::vector<std::vector<T>> bridges;
434 std::unordered_map<T, bool> visited;
435 std::unordered_map<T, int64_t> in, out;
436 for (T x : _elements) {
440 dfs_bridge(start, -1, timer, visited, in, out, bridges);
445 std::unordered_map<T, bool> visited;
448 for (
auto &ele : adj) {
449 if (adj[ele.first].size() != 0) {
460 visited[start] =
true;
464 for (T &x : adj[current]) {
465 if (visited.find(x) == visited.end()) {
472 for (T x : _elements) {
473 if (visited.find(x) == visited.end() && adj[x].size() > 0) {
481 if (this->connected() ==
false) {
486 for (
auto &el : adj) {
487 if (adj[el.first].size() & 1) {
495 return (odd) ? 1 : 2;
498 #ifdef GRAPH_VISUALIZATION_H
501 if (_type ==
"directed") {
502 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
503 for (
auto &[element, neighbors] : adj) {
504 for (T &x : neighbors) {
512 for (
auto &[element, neighbors] : adj) {
513 for (T &x : neighbors) {
514 s += std::to_string(element);
516 s += std::to_string(x);
522 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
523 for (
auto &[element, neighbors] : adj) {
524 for (T &x : neighbors) {
532 for (
auto &[element, neighbors] : adj) {
533 for (T &x : neighbors) {
534 s += std::to_string(element);
536 s += std::to_string(x);
543 if (_type ==
"directed") {
544 digraph_visualization::visualize(s);
546 graph_visualization::visualize(s);
563 std::vector<std::pair<std::pair<T, T>, int64_t>> _adj = {}) {
565 if (_type ==
"directed" || _type ==
"undirected") {
568 throw std::invalid_argument(
"Can't recognize the type of graph");
571 for (
size_t i = 0; i < _adj.size(); i++) {
572 this->
add_edge(_adj[i].first.first, _adj[i].first.second,
576 }
catch (std::invalid_argument &e) {
577 std::cerr << e.what() <<
'\n';
599 _elements = g._elements;
617 if (_type ==
"undirected") {
618 adj[u].push_back(std::make_pair(v, w));
619 adj[v].push_back(std::make_pair(u, w));
620 }
else if (_type ==
"directed") {
621 adj[u].push_back(std::make_pair(v, w));
634 if (_elements.find(start) == _elements.end()) {
637 for (std::pair<T, double> &x : adj[start]) {
638 if (x.first == end) {
657 bool empty() {
return _elements.empty(); }
670 std::vector<T>
dfs(T start);
677 std::vector<T>
bfs(T start);
710 int64_t
prim(T start);
723 std::vector<std::vector<T>>
bridge(T start);
764 for (T &x : elements) {
777 std::unordered_map<T, std::vector<std::pair<T, double>>> adj;
779 std::unordered_set<T> _elements;
784 void dfs_bridge(T start, T parent, int64_t &time,
785 std::unordered_map<T, bool> &visited,
786 std::unordered_map<T, int64_t> &in,
787 std::unordered_map<T, int64_t> &out,
788 std::vector<std::vector<T>> &bridges) {
789 visited[start] =
true;
790 in[start] = out[start] = time++;
791 for (std::pair<T, double> &x : adj[start]) {
792 if (x.first != parent) {
793 if (visited.find(x.first) == visited.end()) {
794 dfs_bridge(x.first, start, time, visited, in, out, bridges);
795 if (out[x.first] > in[start]) {
796 bridges.push_back({x.first, start});
799 out[start] = std::min(out[start], out[x.first]);
806 return _elements.size();
810 if (_elements.find(start) == _elements.end()) {
811 std::cout <<
"Element: " << start <<
" is not found in the Graph" <<
'\n';
814 if (_elements.find(end) == _elements.end()) {
815 std::cout <<
"Element: " << end <<
" is not found in the Graph" <<
'\n';
819 if (!cycle() && _type ==
"directed") {
820 std::vector<T> top_sort = topological_sort();
821 std::reverse(top_sort.begin(), top_sort.end());
823 std::unordered_map<T, double> dist;
824 for (
auto &x : _elements) {
825 dist[x] = std::numeric_limits<int64_t>::max();
828 while (!top_sort.empty()) {
829 auto current = top_sort.back();
831 if (dist[current] != std::numeric_limits<int64_t>::max()) {
832 for (std::pair<T, double> &x : adj[current]) {
833 if (dist[x.first] > dist[current] + x.second) {
834 dist[x.first] = dist[current] + x.second;
835 top_sort.push_back(x.first);
840 return (dist[end] != std::numeric_limits<int64_t>::max()) ? dist[end] : -1;
842 std::unordered_map<T, double> dist;
843 for (
auto &x : _elements) {
844 dist[x] = std::numeric_limits<int64_t>::max();
846 std::priority_queue<std::pair<double, T>,
847 std::vector<std::pair<double, T>>,
848 std::greater<std::pair<double, T>>>
850 pq.push(std::make_pair(0, start));
852 while (!pq.empty()) {
853 T currentNode = pq.top().second;
854 double currentDist = pq.top().first;
856 for (std::pair<T, double> &edge : adj[currentNode]) {
857 if (currentDist + edge.second < dist[edge.first]) {
858 dist[edge.first] = currentDist + edge.second;
859 pq.push(std::make_pair(dist[edge.first], edge.first));
863 return (dist[end] != std::numeric_limits<int64_t>::max()) ? dist[end] : -1;
871 if (this->empty() || _elements.find(start) == _elements.end()) {
875 std::unordered_map<T, bool> visited;
877 visited[start] =
true;
879 int64_t size = s.size();
880 for (int64_t i = 0; i < size; i++) {
882 path.push_back(current);
884 for (std::pair<T, double> &x : adj[current]) {
885 if (visited.find(x.first) == visited.end()) {
887 visited[x.first] =
true;
897 if (this->empty() || _elements.find(start) == _elements.end()) {
901 std::unordered_map<T, bool> visited;
903 visited[start] =
true;
905 int64_t size = q.size();
906 for (int64_t i = 0; i < size; i++) {
907 T current = q.front();
908 path.push_back(current);
910 for (std::pair<T, double> &x : adj[current]) {
911 if (visited.find(x.first) == visited.end()) {
913 visited[x.first] =
true;
922 auto explore = [&](std::unordered_map<T, bool> &visited, T element) ->
void {
925 visited[element] =
true;
929 for (std::pair<T, double> &x : adj[current]) {
930 if (visited.find(x.first) == visited.end()) {
932 visited[x.first] =
true;
937 size_t n = _elements.size();
939 std::unordered_map<T, bool> visited;
940 for (T x : _elements) {
941 if (visited.find(x) == visited.end()) {
950 std::unordered_map<T, int> indeg;
954 for (T x : _elements) {
955 for (std::pair<T, double> &y : adj[x]) {
960 for (T x : _elements) {
967 T current = q.front();
970 for (std::pair<T, double> &x : adj[current]) {
971 if (--indeg[x.first] == 0) {
980 std::vector<T> top_sort;
981 std::unordered_map<T, bool> visited;
982 std::unordered_map<T, int64_t> indeg;
983 for (T x : _elements) {
984 for (std::pair<T, double> &y : adj[x]) {
990 for (T x : _elements) {
998 T current = q.front();
1000 top_sort.push_back(current);
1001 for (std::pair<T, double> &x : adj[current]) {
1002 if (visited.find(x.first) == visited.end()) {
1003 if (--indeg[x.first] == 0) {
1005 visited[x.first] =
true;
1015 std::priority_queue<std::pair<T, int64_t>, std::vector<std::pair<T, int64_t>>,
1016 std::greater<std::pair<T, int64_t>>>
1018 std::unordered_map<T, bool> visited;
1020 q.push(std::make_pair(0, _temp));
1021 while (!q.empty()) {
1022 std::pair<T, int64_t> current = q.top();
1024 _temp = current.first;
1025 if (visited.find(_temp) != visited.end()) {
1028 cost += current.second;
1029 visited[_temp] =
true;
1030 for (std::pair<T, double> &x : adj[current.first]) {
1031 if (visited.find(x.first) == visited.end()) {
1040 std::unordered_map<T, int> color;
1041 std::queue<std::pair<T, int>> q;
1043 for (T x : _elements) {
1044 if (color.find(x) == color.end()) {
1047 while (!q.empty()) {
1048 std::pair<T, int> current = q.front();
1050 T v = current.first;
1051 int col = current.second;
1052 for (std::pair<T, double> &x : adj[v]) {
1053 if (color.find(x.first) != color.end() && color[x.first] == col) {
1056 if (color.find(x.first) == color.end()) {
1057 color[x.first] = (col) ? 0 : 1;
1058 q.push({x.first, color[x.first]});
1067 template <
typename T>
1070 std::vector<std::vector<T>> bridges;
1071 std::unordered_map<T, bool> visited;
1072 std::unordered_map<T, int64_t> in, out;
1073 for (T x : _elements) {
1077 dfs_bridge(start, -1, timer, visited, in, out, bridges);
1082 std::unordered_map<T, bool> visited;
1085 for (
auto &ele : adj) {
1086 if (adj[ele.first].size() != 0) {
1097 visited[start] =
true;
1098 while (!s.empty()) {
1099 T current = s.top();
1101 for (std::pair<T, double> &x : adj[current]) {
1102 if (visited.find(x.first) == visited.end()) {
1103 visited[x.first] =
true;
1109 for (T x : _elements) {
1110 if (visited.find(x) == visited.end() && adj[x].size() > 0) {
1118 if (this->connected() ==
false) {
1123 for (
auto &el : adj) {
1124 if (adj[el.first].size() & 1) {
1133 return (odd) ? 1 : 2;
1136 template <
typename T>
1138 std::unordered_map<T, double> dist;
1142 dist[it.first] = std::numeric_limits<double>::infinity();
1149 for (
int i = 0; i < v - 1; i++)
1150 for (
const auto j : adj)
1151 for (
const auto edge : adj[j.first])
1152 if (dist[j.first] + edge.second < dist[edge.first])
1153 dist[edge.first] = dist[j.first] + edge.second;
1158 for (
int i = 0; i < v - 1; i++)
1159 for (
const auto j : adj)
1160 for (
const auto edge : adj[j.first])
1161 if (dist[j.first] + edge.second < dist[edge.first])
1162 dist[edge.first] = -std::numeric_limits<double>::infinity();
1168 #ifdef GRAPH_VISUALIZATION_H
1171 if (_type ==
"directed") {
1172 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
1173 for (
auto &[element, neighbors] : adj) {
1174 for (std::pair<T, double> &x : neighbors) {
1175 if (x.first == element) {
1182 s += std::to_string(x.second);
1188 for (
auto &[element, neighbors] : adj) {
1189 for (std::pair<T, double> &x : neighbors) {
1190 if (x.first == element) {
1193 s += std::to_string(element);
1195 s += std::to_string(x.first);
1197 s += std::to_string(x.second);
1204 if (std::is_same_v<T, char> || std::is_same_v<T, std::string>) {
1205 for (
auto &[element, neighbors] : adj) {
1206 for (std::pair<T, double> &x : neighbors) {
1207 if (x.first == element) {
1214 s += std::to_string(x.second);
1220 for (
auto &[element, neighbors] : adj) {
1221 for (std::pair<T, double> &x : neighbors) {
1222 if (x.first == element) {
1225 s += std::to_string(element);
1227 s += std::to_string(x.first);
1229 s += std::to_string(x.second);
1236 if (_type ==
"directed") {
1237 digraph_visualization::visualize(s);
1239 graph_visualization::visualize(s);
Class for Unweighted Graph.
Definition: graph.h:27
int64_t scc()
scc(strongly connected components) function.
bool bipartite()
bipartite function.
Definition: graph.h:403
void add_edge(T u, T v)
add_edge function
Definition: graph.h:87
std::vector< T > bfs(T start)
bfs function
Definition: graph.h:284
std::vector< std::vector< T > > bridge(T start)
bridge function.
Definition: graph.h:431
graph & operator=(const graph &g)
operator = for the graph class
Definition: graph.h:70
bool has_edge(T start, T end)
has_edge function.
Definition: graph.h:105
friend std::ostream & operator<<(std::ostream &out, graph< T > &g)
operator << for the graph class.
Definition: graph.h:214
std::vector< T > dfs(T start)
dfs function
Definition: graph.h:261
std::vector< T > topological_sort()
topological_sort function.
Definition: graph.h:368
graph(std::string _type, std::vector< std::pair< T, std::vector< T >>> _adj={})
Constructor for the unweighted graph.
Definition: graph.h:35
bool cycle()
cycle function.
Definition: graph.h:338
void visualize()
visualize function.
void clear()
clear function Clearing the entire graph.
Definition: graph.h:121
~graph()
Destroy the graph object.
Definition: graph.h:80
bool connected()
connected function.
Definition: graph.h:444
size_t size()
size function
Definition: graph.h:259
int64_t connected_components()
connected_components function.
Definition: graph.h:310
graph(const graph &g)
Construct a new graph object.
Definition: graph.h:61
int eulerian()
eulerian function.
Definition: graph.h:480
bool empty()
empty function Checks if a graph is empty.
Definition: graph.h:130
class for weighted graph
Definition: graph.h:554
int eulerian()
eulerian function.
Definition: graph.h:1117
int64_t scc()
scc(strongly connected components) function.
double shortest_path(T start, T end)
shortest_path function.
Definition: graph.h:809
int64_t connected_components()
connected_components function.
Definition: graph.h:921
~weighted_graph()
Destroy the weighted graph object.
Definition: graph.h:608
bool bipartite()
bipartite function.
Definition: graph.h:1039
std::vector< std::vector< T > > bridge(T start)
bridge function.
Definition: graph.h:1068
bool has_edge(T start, T end)
has_edge function.
Definition: graph.h:633
weighted_graph(const weighted_graph &g)
Copy constructor for weighted graph class.
Definition: graph.h:586
bool cycle()
cycle function.
Definition: graph.h:949
std::vector< T > topological_sort()
topological sort function.
Definition: graph.h:979
std::vector< T > bfs(T start)
bfs function.
Definition: graph.h:895
friend std::ostream & operator<<(std::ostream &out, weighted_graph< T > &g)
<< operator for the weighted graph class.
Definition: graph.h:761
weighted_graph(std::string _type, std::vector< std::pair< std::pair< T, T >, int64_t >> _adj={})
Constructor for weighted graph.
Definition: graph.h:562
bool empty()
empty function.
Definition: graph.h:657
bool connected()
connected function.
Definition: graph.h:1081
void visualize()
visualize function.
std::unordered_map< T, double > bellman_ford(T start)
find SSSP and identify negative cycles.
Definition: graph.h:1137
std::vector< T > dfs(T start)
dfs function.
Definition: graph.h:868
void add_edge(T u, T v, int64_t w)
add_edge function.
Definition: graph.h:616
size_t size()
size function.
Definition: graph.h:805
void clear()
clear function. Clearing the entire graph.
Definition: graph.h:649
int64_t prim(T start)
prim function.
Definition: graph.h:1014
weighted_graph & operator=(const weighted_graph &g)
operator = for weighted graph class
Definition: graph.h:597