// show shortest chain of relationships between name1 and name2 private static void ShowBingo(string name1, string name2) { GraphNode start = rg.GetNode(name1); GraphNode end = rg.GetNode(name2); // invalid case - start not in file if (start == null) { Console.WriteLine("\t{0} not found", name1); } // invalid case - end not in file else if (end == null) { Console.WriteLine("\t{0} not found", name2); } // invalid case - start is same as end else if (start == end) { Console.WriteLine("\t{0} and {1} are the same", name1, name2); } // valid case - start and end are in file, and are different nodes else { // list of nodes that will store the shortest path nodes List <GraphNode> shortestPath = new List <GraphNode>(); // list of list of nodes that will store different paths from start to end List <List <GraphNode> > paths = new List <List <GraphNode> >(); // list of nodes that will store the information of current depth nodes List <GraphNode> currentDepth = new List <GraphNode>(); // dictionary to keep track of which nodes have been added and visited Dictionary <string, bool> check = new Dictionary <string, bool>(); currentDepth.Add(start); paths.Add(currentDepth); int depthCount = 0; while (true) { // new unique path currentDepth = new List <GraphNode>(); // BFS // for each node in the last path stored foreach (GraphNode n in paths[paths.Count - 1]) { // for each edge for the current node foreach (GraphEdge e in n.GetEdges()) { // if this edge leads to end, go to label if (e.To() == end.GetName()) { goto Found; } // otherwise update current path, and add it to our dictionary if not in there already if (!check.ContainsKey(e.To())) { currentDepth.Add(e.ToNode()); check.Add(e.To(), true); } } } // add new unique path to list of paths paths.Add(currentDepth); } Found: shortestPath.Add(end); depthCount = paths.Count - 1; // while the last node in shortest path is not the same as start node, keep adding nodes to shortestPath list // from end to start checking to see if they are in our paths list while (shortestPath[shortestPath.Count - 1] != start && depthCount >= 0) { // for each edge of last node in shortest path foreach (GraphEdge e in shortestPath[shortestPath.Count - 1].GetEdges()) { if (paths[depthCount].Contains(e.ToNode())) { shortestPath.Add(e.ToNode()); goto NextLoop; } } // for each node in this depth foreach (GraphNode n in paths[depthCount]) { foreach (GraphEdge e in n.GetEdges()) { if (e.ToNode() == shortestPath[shortestPath.Count - 1]) { shortestPath.Add(n); goto NextLoop; } } } // decrement depthCount for next iteration NextLoop: depthCount--; } // reverse order shortestPath to get order from start to end, since it is in reverse order (end to start) right now shortestPath.Reverse(); // output in line the relationship sentence for each edge in shortest path for (int i = 1; i < shortestPath.Count; i++) { foreach (GraphEdge e in shortestPath[i - 1].GetEdges()) { if (e.ToNode() == shortestPath[i]) { Console.WriteLine("\t" + shortestPath[i - 1].GetName() + " is a " + e.Label.Substring(3).ToLower() + " of " + shortestPath[i].GetName()); } } } } }