26 using weight_type = T;
33template<
typename EdgeT>
44enum class EdgeOrientation {
76template<
typename VertexT>
79 using vertex_type = VertexT;
80 using edge_type =
typename VertexT::edge_type;
83 adjacency_list(EdgeOrientation edge_orientation = EdgeOrientation::Undirected) : _edge_orientation(edge_orientation) {}
86 adjacency_list(
size_t vertex_count, EdgeOrientation edge_orientation = EdgeOrientation::Undirected) : _edge_orientation(edge_orientation) {
98 return _edge_orientation == EdgeOrientation::Directed;
108 return _vertices.empty();
113 return _vertices.size();
118 size_t count = std::accumulate(_vertices.begin(), _vertices.end(), 0, [](
const vertex_type&
vertex,
size_t count) { return count + vertex.edges.size(); });
127 std::for_each(_vertices.begin(), _vertices.end(), [](vertex_type&
vertex) { vertex.edges.clear(); });
136 const vertex_type&
vertex(
size_t i)
const {
142 std::vector<edge_type> edges;
143 for(
const auto&
vertex : _vertices)
150 _vertices.push_back(
vertex);
151 return _vertices.size() - 1;
163 edge_type reverse_edge =
edge;
164 std::swap(reverse_edge.start, reverse_edge.end);
190 return !topological_sort_impl();
199 if(has_cycle_undirected_breadth_first(i, visited))
210 std::vector<size_t> topological_sort()
const {
211 std::vector<size_t> vertices;
212 if(!topological_sort_impl(&vertices))
219 bool has_cycle_undirected_breadth_first(
size_t start, std::vector<bool>& visited)
const {
221 std::queue<std::pair<size_t, size_t>> edge_queue;
224 constexpr size_t nindex =
static_cast<size_t>(-1);
227 edge_queue.push({ start, nindex });
228 visited[start] =
true;
230 while(!edge_queue.empty()) {
231 size_t node = edge_queue.front().first;
232 size_t parent = edge_queue.front().second;
236 for(
const edge_type& edge :
vertex(node).edges) {
239 if(!visited[edge.end]) {
240 visited[edge.end] =
true;
241 edge_queue.push({ edge.end, node });
242 }
else if(edge.end != parent) {
255 bool topological_sort_impl(std::vector<size_t>* ordered_vertices =
nullptr)
const {
263 for(
const vertex_type& vertex : _vertices) {
264 for(
const edge_type& edge :
vertex.edges)
265 in_degree[edge.end]++;
268 std::queue<size_t> vertex_queue;
271 for(
size_t i = 0; i < in_degree.size(); ++i) {
272 if(in_degree[i] == 0)
273 vertex_queue.push(i);
280 size_t visited_count = 0;
283 while(!vertex_queue.empty()) {
284 size_t i = vertex_queue.front();
292 ordered_vertices->push_back(i);
295 for(
const auto& edge :
vertex(i).edges) {
296 in_degree[edge.end]--;
297 if(in_degree[edge.end] == 0) {
299 vertex_queue.push(edge.end);
309 std::vector<vertex_type> _vertices;
311 EdgeOrientation _edge_orientation = EdgeOrientation::Undirected;
314using graph = adjacency_list<vertex<edge>>;
316using 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 already exists, true otherwise
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