Professional Documents
Culture Documents
Bfs
Bfs
#include <cassert>
#include <cstdarg>
#include <iomanip>
#include <cstdint>
#include <iostream>
#include <memory>
#include <limits>
#include <optional>
#include <array>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <random>
#include <type_traits>
return buf;
}
struct Graph {
Graph() : Graph(false, 0) {}
Graph(bool directed, size_t vertices) : _dir(directed), _adj(vertices) {}
Graph(bool directed, const std::vector<std::vector<size_t>>& adj)
: Graph(directed, adj.size()) {
for (size_t i = 0; i < adj.size(); i++)
for (size_t v : adj[i]) add_edge(Vertex{i}, Vertex{v});
}
bool is_directed() const { return _dir; }
size_t vertices() const { return _adj.size(); }
if (!_seen.empty()) {
CHECK(!_seen[v], "Graph: vertex %zu examined second time", size_t(v));
_seen[v] = true;
}
return _adj[v];
}
struct Iterator {
Iterator() = default;
private:
friend struct Graph;
Iterator(size_t v) : _v(v) {}
size_t _v = NO_VERTEX;
};
private:
bool _dir;
std::vector<std::vector<Vertex>> _adj;
mutable std::vector<bool> _seen;
};
// - Arrays P and D have the correct size and are set to NO_VERTEX resp.
NO_DISTANCE
// before calling bfs.
// - Function bfs must set predecesor of u to ROOT.
// - Return value is the number of visited vertices.
size_t bfs(const Graph& G, Vertex u, std::vector<Vertex>& Predesor,
std::vector<size_t>& Distance) {
std::queue<Vertex> q;
q.push(u);
Distance[u] = 0;
Predesor[u] = ROOT;
size_t visitedVertices = 0;
while (!q.empty()) {
Vertex v = q.front();
q.pop();
visitedVertices++;
}
return visitedVertices;
#ifndef __PROGTEST__
struct RandomGraphGenerator {
RandomGraphGenerator(uint32_t seed) : my_rand(seed) {}
return G;
}
return G;
}
private:
std::mt19937 my_rand;
};
G.bfs_debug_begin();
size_t seen_t = bfs(G, u, P, D);
G.bfs_debug_end();
for (Vertex v : G) {
if (P[v] == NO_VERTEX) {
CHECK(D[v] == NO_DISTANCE, "P[%zu] == NO_VERTEX but D[%u] == %zu not
NO_DISTANCE.",
size_t(v), size_t(v), D[v]);
pred_ok[v] = true;
continue;
}
if (v != u) {
CHECK(P[v] < G.vertices(),
"P[%zu] == %zu >= %zu (# of vertices).", size_t(v), size_t(P[v]),
G.vertices());
CHECK(P[P[v]] != NO_VERTEX,
"P[%zu] == %zu but P[%zu] == NO_VERTEX.", size_t(v), size_t(P[v]),
size_t(P[v]));
}
if (P[w] != v) continue;
size_t seen_r = 0;
for (Vertex v : G) {
CHECK(pred_ok[v], "P[%zu] == %zu but there is no edge.", size_t(v),
size_t(P[v]));
seen_r += (P[v] != NO_VERTEX);
}
CHECK(seen_r == seen_t,
"Reported size of component is %zu but it should be %zu.", seen_t, seen_r);
}
void run_tests() {
std::cout << "Hardcoded graphs..." << std::endl;
for (const Graph& G : SMALL_GRAPHS) for (Vertex u : G) test_bfs(G, u);
RandomGraphGenerator rgg(53323);
std::cout << "Small random graphs..." << std::endl;
for (size_t i = 0; i < 30; i++) {
Graph G = rgg.graph1(10 + i, 4*(10 + i));
Vertex u = rgg.vertex(G);
test_bfs(G, u);
}
for (size_t i = 0; i < 30; i++) {
Graph G = rgg.graph2(10 + i, 0.7);
Vertex u = rgg.vertex(G);
test_bfs(G, u);
}
int main() {
try {
run_tests();
#endif