#ifndef GRAPH_H_ #define GRAPH_H_ #include #include #include #include namespace graph { // Forward declerations template class Graph; template std::ostream& operator<<(std::ostream& os, Graph& G); template class Graph { public: ~Graph(); // Return true if there is a path from u to v virtual bool contains(const T& u, const T& v) =0; // Add edge e(u,v) virtual void insert(const T& u, const T& v) =0; // Remove edge e(u,v) virtual void remove(const T& u, const T& v) =0; // Return graph vertices auto vertices(); // Return num. of vertices std::uint16_t V(); // Return num. of edges std::uint16_t E(); // Adjacency matrix representation std::unordered_map> adjList; friend std::ostream& operator<<<>(std::ostream& os, Graph& G); }; template Graph::~Graph() { adjList.clear(); } template auto Graph::vertices() { return std::views::keys(adjList); } template std::uint16_t Graph::V() { return static_cast(adjList.size()); } template std::uint16_t Graph::E() { std::uint16_t edges = 0; for (const auto& u : vertices()) { edges += static_cast(adjList[u].size()); } return static_cast(edges); } template std::ostream& operator<<(std::ostream& os, Graph& G) { os << "V: " << G.V() << " E: " << G.E() << '\n'; for (const auto& u : this->vertices()) { if (!this->adjList[u].empty()) { for (const auto& v : this->adjList[u]) { os << u << "->" << v << ' '; } os << '\n'; } } os << '\n'; return os; } } // namespace graph #endif