using System.Collections.Generic; namespace graphs { class BFS where T : notnull { private Graph graph; private Dictionary Distance = new Dictionary(); private Dictionary Parent = new Dictionary(); private Dictionary State = new Dictionary(); public BFS(Graph graph) { this.graph = graph; } public BFS Run() { foreach (var vertex in graph.Vertices) { if (ColorOf(vertex) == Color.White) { RunFrom(vertex); } } return this; } public BFS RunFrom(T start) { State[start] = Color.Gray; Distance[start] = 0; Parent[start] = default(T); var queue = new Queue(); queue.Enqueue(start); while (queue.Count > 0) { var u = queue.Dequeue(); for (var iterator = graph.GetEdgesFrom(u); iterator.MoveNext();) { var v = iterator.Current; if (GetOrDefault(State, v, Color.White) == Color.White) { State[v] = Color.Gray; Distance[v] = Distance[u] + 1; Parent[v] = u; queue.Enqueue(v); } } State[u] = Color.Black; } return this; } private static V GetOrDefault(Dictionary flags, U u, V defaultValue) where U : notnull { if (flags.TryGetValue(u, out var flag)) { return flag; } return defaultValue; } public int DistanceTo(T u) => GetOrDefault(Distance, u, 0); public T? ParentOf(T u) => GetOrDefault(Parent, u, default(T)); public Color ColorOf(T u) => GetOrDefault(State, u, Color.White); } }