// For example, edges like (0, 1), (1, 2) => there's an edge between vertices 0 and 1 and 1 and 2. // Creating from edges also initializes depths and subtree sizes, because we have to DFS regardless. public static RootedTree CreateFromEdges(int vertexCount, int rootID, int[,] edges) { var tree = new RootedTree(vertexCount, rootID); for (int i = 0; i < vertexCount - 1; ++i) { var firstVertex = tree.Vertices[edges[i, 0]]; var secondVertex = tree.Vertices[edges[i, 1]]; firstVertex.AddNeighbor(secondVertex); secondVertex.AddNeighbor(firstVertex); } // Now we need to wire up the parent-child relationships. We have to DFS just like // InitializeDepthsAndSubtreeSizes, so we might as well initialize depths & subtree sizes too. var verticesToVisit = new Stack <Vertex>(); verticesToVisit.Push(tree.Root); while (verticesToVisit.Count > 0) { var vertex = verticesToVisit.Peek(); // If Depth is null, it's the first time we're visiting the vertex. Visit its children. if (!vertex.Depth.HasValue) { vertex.Depth = 1 + (vertex.Parent?.Depth ?? -1); foreach (var child in vertex.Neighbors.Where(n => n != vertex.Parent)) { child.SetParent(vertex); verticesToVisit.Push(child); } } // At this point, we know all the children have been visited, so we're good to pop. else { verticesToVisit.Pop(); vertex.SubtreeSize = 1 + vertex.Children.Sum(c => c.SubtreeSize); } } return(tree); }
// E.g. if verticesChildren[1] = (3, 4, 6), vertices w/ ID 3, 4, 6 are children of vertex w/ ID 1. // Creating from children doesn't initialize depths or subtree sizes; do that separately if needed. public static RootedTree CreateFromChildren(int vertexCount, int rootID, List <int>[] verticesChildren) { var tree = new RootedTree(vertexCount, rootID); for (int id = 0; id < vertexCount; ++id) { if (!verticesChildren[id]?.Any() ?? true) { continue; } var parent = tree.Vertices[id]; foreach (int childID in verticesChildren[id]) { tree.Vertices[childID].SetParent(parent); } } return(tree); }
internal Vertex(RootedTree tree, int ID) { _tree = tree; this.ID = ID; }