private void PrepareTree()
        {
            int          centerCount = 0;
            List <int[]> allCenters  = new List <int[]>(forest.NumberOfTrees);

            int[] roots = forest.GetRoots();
            foreach (int rId in roots)
            {
                int[] centers = forest.GetCenter(rId);
                centerCount += centers.Length;
                allCenters.Add(centers);
            }

            foreach (int[] centers in allCenters)
            {
                forest.SetToRoot(centers[0]);
            }

            if (centerCount > 1)
            {
                // Forest is not connected or has two centers.
                // Add dummy root.

                isDummyRoot = true;
                rootId      = forest.AddVertex();

                foreach (int[] centers in allCenters)
                {
                    foreach (int c in centers)
                    {
                        forest.SetParent(c, rootId);
                    }
                }
            }
            else
            {
                isDummyRoot = false;
                rootId      = allCenters[0][0];
            }
        }
        private void Preprocess()
        {
            hypertree.TransformToDual();

            // Generate and "draw" underlying tree.
            joinForest = hypertree.GetJoinTree();
            drawer     = new RootedDrawing(joinForest);
            data       = drawer.DrawRadial();

            // Computes colouring and max colour.
            colouring = hypertree.GetVertexColouring();
            hypertree.TransformToDual();

            maxCol = 0;
            for (int i = 0; i < colouring.Length; i++)
            {
                maxCol = Math.Max(colouring[i], maxCol);
            }

            // Counting sort to sort edges by their colour.
            edgeByColour = new int[colouring.Length];
            int[] colCounter = new int[maxCol + 1];

            for (int i = 0; i < colouring.Length; i++)
            {
                colCounter[colouring[i]]++;
            }

            for (int i = 1; i < colCounter.Length; i++)
            {
                colCounter[i] += colCounter[i - 1];
            }

            for (int i = colouring.Length - 1; i >= 0; i--)
            {
                int col = colouring[i];

                colCounter[col]--;
                int ind = colCounter[col];

                edgeByColour[ind] = i;
            }
            // End of counting sort.

            Array.Reverse(edgeByColour);

            edges = new List <int> [hypertree.NoOfEdges];
            for (int i = 0; i < edges.Length; i++)
            {
                edges[i] = new List <int>(Math.Max(hypertree.GetCardinality(i) * 2 - 2, 0));
            }

            // Use a DFS to determine the tree-edges of each hyperedge.
            // The search starts at the root.
            // Each time the search reaces a vertex v, it checks for all edges e containing v, if e is already activated.
            // If e is already activated, the tree-edge from v to its parent is part of the edge.

            bool[]      activeEdges = new bool[hypertree.NoOfEdges];
            Stack <int> verStack    = new Stack <int>();
            Stack <int> parStack    = new Stack <int>();

            int[] rootIds = joinForest.GetRoots();
            foreach (int rId in rootIds)
            {
                verStack.Push(rId);
                parStack.Push(-1);

                while (verStack.Count > 0)
                {
                    int vId = verStack.Pop();
                    int pId = parStack.Pop();

                    int[] edgeIds = hypertree.GetEdges(vId);

                    foreach (int eId in edgeIds)
                    {
                        if (activeEdges[eId])
                        {
                            edges[eId].Add(pId);
                            edges[eId].Add(vId);
                        }

                        activeEdges[eId] = true;
                    }

                    int[] neighs = joinForest[vId];

                    foreach (int nId in neighs)
                    {
                        if (nId == pId)
                        {
                            continue;
                        }

                        verStack.Push(nId);
                        parStack.Push(vId);
                    }
                }
            }

            // Now, data contains the radial coordinates of each vertex,
            // edges contains the list of tree-edges of each hyperedge,
            // colouring contains the colours of each hyperedge,
            // and edgeByColur has the edges ordered by their colour.
        }