Following the implementation of the disjointset, another fun algorithm to implement was the offline least common ancestor problem. Tarjan proposed a algorithm based on the disjoint-set and a DFS traversal. Given that I now have all those ingredients in QuickGraph, it was just a matter of hooking together the implementation with the right events. The beef of the implementation looks as follows (and looks quite elegant to me):
var gpair = GraphExtensions.ToAdjacencyGraph(this.pairs); // for fast lookup var disjointSet = new ForestDisjointSet(); var vancestors = new Dictionary(); var dfs = new DepthFirstSearchAlgorithm(this, this.VisitedGraph, new DictionaryGraphColor>(this.VisitedGraph.VertexCount)); dfs.InitializeVertex += (sender, args) => disjointSet.MakeSet(args.Vertex); dfs.DiscoverVertex += (sender, args) => vancestors[args.Vertex] = args.Vertex; dfs.TreeEdge += (sender, args) => { var edge = args.Edge; disjointSet.Union(edge.Source, edge.Target); vancestors[disjointSet.FindSet(edge.Source)] = edge.Source; }; dfs.FinishVertex += (sender, args) => { foreach (var e in gpair.OutEdges(args.Vertex)) if (dfs.VertexColors[e.Target] == GraphColor.Black) this.ancestors[EdgeExtensions.ToVertexPair(e)] = vancestors[disjointSet.FindSet(e.Target)]; }; // go! dfs.Compute(root);
Enjoy!
Page rendered at Thursday, September 02, 2010 2:52:38 PM (Pacific Daylight Time, UTC-07:00)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.