25 using weight_type = T;
32template<
typename EdgeT>
43enum class EdgeOrientation {
75template<
typename VertexT>
78 using vertex_type = VertexT;
79 using edge_type =
typename VertexT::edge_type;
82 adjacency_list(EdgeOrientation edge_orientation = EdgeOrientation::Undirected) : _edge_orientation(edge_orientation) {}
85 adjacency_list(
size_t vertex_count, EdgeOrientation edge_orientation = EdgeOrientation::Undirected) : _edge_orientation(edge_orientation) {
97 return _edge_orientation == EdgeOrientation::Directed;
107 return _vertices.empty();
112 return _vertices.size();
117 size_t count = std::accumulate(_vertices.begin(), _vertices.end(), 0, [](
const vertex_type&
vertex,
size_t count) { return count + vertex.edges.size(); });
126 std::for_each(_vertices.begin(), _vertices.end(), [](vertex_type&
vertex) { vertex.edges.clear(); });
135 const vertex_type&
vertex(
size_t i)
const {
141 std::vector<edge_type> edges;
142 for(
const auto&
vertex : _vertices)
149 _vertices.push_back(
vertex);
150 return _vertices.size() - 1;
162 edge_type reverse_edge =
edge;
163 std::swap(reverse_edge.start, reverse_edge.end);
189 return !topological_sort_impl();
198 if(has_cycle_undirected_breadth_first(i, visited))
209 std::vector<size_t> topological_sort()
const {
210 std::vector<size_t> vertices;
211 if(!topological_sort_impl(&vertices))
218 bool has_cycle_undirected_breadth_first(
size_t start, std::vector<bool>& visited)
const {
220 std::queue<std::pair<size_t, size_t>> edge_queue;
223 constexpr size_t nindex =
static_cast<size_t>(-1);
226 edge_queue.push({ start, nindex });
227 visited[start] =
true;
229 while(!edge_queue.empty()) {
230 size_t node = edge_queue.front().first;
231 size_t parent = edge_queue.front().second;
235 for(
const edge_type& edge :
vertex(node).edges) {
238 if(!visited[edge.end]) {
239 visited[edge.end] =
true;
240 edge_queue.push({ edge.end, node });
241 }
else if(edge.end != parent) {
254 bool topological_sort_impl(std::vector<size_t>* ordered_vertices =
nullptr)
const {
262 for(
const vertex_type& vertex : _vertices) {
263 for(
const edge_type& edge :
vertex.edges)
264 in_degree[edge.end]++;
267 std::queue<size_t> vertex_queue;
270 for(
size_t i = 0; i < in_degree.size(); ++i) {
271 if(in_degree[i] == 0)
272 vertex_queue.push(i);
279 size_t visited_count = 0;
282 while(!vertex_queue.empty()) {
283 size_t i = vertex_queue.front();
291 ordered_vertices->push_back(i);
294 for(
const auto& edge :
vertex(i).edges) {
295 in_degree[edge.end]--;
296 if(in_degree[edge.end] == 0) {
298 vertex_queue.push(edge.end);
308 std::vector<vertex_type> _vertices;
310 EdgeOrientation _edge_orientation = EdgeOrientation::Undirected;
313using graph = adjacency_list<vertex<edge>>;
315using weighted_graph = adjacency_list<vertex<weighted_edge<T>>>;
A graph represented as an adjacency list.
adjacency_list(size_t vertex_count, EdgeOrientation edge_orientation=EdgeOrientation::Undirected)
create a graph with the given edge_orientation and vertex_count default-initialized vertices and zero...
size_t add_vertex(const vertex_type &vertex)
add a new vertex to graph and return its index
void remove_all_edges()
removes all edges
bool is_directed() const
return true if the graph is directed
vertex_type & vertex(size_t i)
access to vertex i
size_t vertex_count() const
return the number of vertices, i.e. the order of the graph
bool add_edge(size_t start, size_t end)
add a default-initialized edge definded by the start and end vertex to the list; return false if the ...
bool edge_exists(size_t start, size_t end) const
check if edge is already in list
void resize(size_t vertex_count)
resize number of vertices, all edge data is removed
size_t edge_count() const
return the number of edges, i.e. the size of the graph
bool empty() const
return true if the graph does not contain any vertices
bool add_edge(const edge_type &edge)
add an edge to the list; return false if the edge or, in case of a directed graph,...
const std::vector< edge_type > to_edge_list() const
return a list of all edges in no particular order
bool is_cyclic() const
return true if the graph contains at least one cycle
const vertex_type & vertex(size_t i) const
const access to vertex i
adjacency_list(EdgeOrientation edge_orientation=EdgeOrientation::Undirected)
create a graph with the given edge_orientation
this header is dependency free
size_t end
the index of the end vertex
size_t start
the index of the start vertex
std::vector< edge_type > edges
incident edges
EdgeT edge_type
the used edge type