Skip to content

Instantly share code, notes, and snippets.

@goldsborough
Created October 10, 2015 22:46
Show Gist options
  • Save goldsborough/5238616e15154af76c0e to your computer and use it in GitHub Desktop.
Save goldsborough/5238616e15154af76c0e to your computer and use it in GitHub Desktop.
Are two vertices in a directed graph connected?
class DirectedGraph
{
public:
using size_t = std::size_t;
using vertex_t = std::size_t;
using adjacent_t = std::vector<vertex_t>;
DirectedGraph(size_t vertices)
: _edges(0)
, _vertices(vertices)
{ }
void add_vertex()
{
_vertices.push_back({});
}
void add_edge(vertex_t from, vertex_t to)
{
_assert_vertex_in_range(from);
_assert_vertex_in_range(to);
_vertices[from].outgoing.push_back(to);
_vertices[to].incoming.push_back(from);
++_edges;
}
void add_route(const std::vector<vertex_t>& route)
{
for (auto j = route.begin(), i = j++, end = route.end();
j != end;
++i, ++j)
{
add_edge(*i, *j);
}
}
adjacent_t incoming(vertex_t vertex) const
{
_assert_vertex_in_range(vertex);
return _vertices[vertex].incoming;
}
adjacent_t outgoing(vertex_t vertex) const
{
_assert_vertex_in_range(vertex);
return _vertices[vertex].outgoing;
}
size_t vertex_number() const
{
return _vertices.size();
}
size_t edge_number() const
{
return _edges;
}
bool is_empty() const
{
return _vertices.empty();
}
private:
struct Vertex { adjacent_t incoming, outgoing; };
void _assert_vertex_in_range(vertex_t vertex) const
{
if (vertex >= _vertices.size())
{
throw std::invalid_argument("Vertex out of range!");
}
}
size_t _edges;
std::vector<Vertex> _vertices;
};
class Is_Connected
{
public:
using vertex_t = DirectedGraph::vertex_t;
bool operator()(const DirectedGraph& graph,
vertex_t vertex,
vertex_t target)
{
bitset_t visited(graph.vertex_number(), false);
return _is_connected(graph, vertex, target, visited);
}
private:
using bitset_t = std::vector<bool>;
bool _is_connected(const DirectedGraph& graph,
vertex_t vertex,
vertex_t target,
bitset_t& visited) const
{
if (visited[vertex]) return false;
if (vertex == target) return true;
visited[vertex] = true;
for (const auto& adjacent : graph.outgoing(vertex))
{
if (_is_connected(graph, adjacent, target, visited))
{
return true;
}
}
return false;
}
};
bool is_connected(const DirectedGraph& graph,
DirectedGraph::vertex_t vertex,
DirectedGraph::vertex_t target)
{
Is_Connected check;
return check(graph, vertex, target);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment