Пример #1
0
        private RootedTreeNode[,] PreprocessLCA()
        {
            int N = RootedTreeNodes.Length, M = 0;

            while ((1 << M) < N)
            {
                M++;
            }
            var p = new RootedTreeNode[N, M];

            for (int i = 0; i < N; i++)
            {
                p[i, 0] = RootedTreeNodes[i].Parent;
            }

            for (int j = 1; 1 << j < N; j++)
            {
                for (int i = 0; i < N; i++)
                {
                    if (p[i, j - 1] != null)
                    {
                        p[i, j] = p[p[i, j - 1].Node.Index, j - 1];
                    }
                }
            }

            return(p);
        }
Пример #2
0
        public RootedTreeNode GetLowestCommonAncestor(RootedTreeNode p, RootedTreeNode q)
        {
            if (lcaPreprocess == null)
            {
                lcaPreprocess = PreprocessLCA();
            }

            if (p.Level < q.Level)
            {
                RootedTreeNode tmp = p;
                p = q;
                q = tmp;
            }

            int log;

            for (log = 1; 1 << log <= p.Level; log++)
            {
                ;
            }
            log--;

            for (int i = log; i >= 0; i--)
            {
                if (p.Level - (1 << i) >= q.Level)
                {
                    p = lcaPreprocess[p.Node.Index, i];
                }
            }

            if (p == q)
            {
                return(p);
            }

            for (int i = log; i >= 0; i--)
            {
                if (lcaPreprocess[p.Node.Index, i] != null &&
                    lcaPreprocess[p.Node.Index, i] != lcaPreprocess[q.Node.Index, i])
                {
                    p = lcaPreprocess[p.Node.Index, i];
                    q = lcaPreprocess[q.Node.Index, i];
                }
            }

            return(p.Parent);
        }
Пример #3
0
        private readonly RootedTreeNode[] topologicalOrder;         // root = topologicalOrder[0]

        public RootedTree(Graph graph, Node root)
        {
            if (graph == null || root == null || root.Graph != graph || graph.Edges.Count != graph.Nodes.Count - 1)
            {
                throw new ArgumentException();
            }
            var n = graph.Nodes.Count;

            RootedTreeNodes = new RootedTreeNode[n];

            // Build up tree structure without using recursion and create a topological ordering
            var level  = new int[n];
            var order  = new int[n];
            var parent = new int[n];

            level[root.Index]  = 0;
            order[0]           = root.Index;
            parent[root.Index] = -1;
            for (int i = 0, j = 1; i < n; i++)
            {
                if (i == j)
                {
                    throw new ArgumentException();
                }
                foreach (var node in graph.GetNode(order[i]).GetAdjacentNodes())
                {
                    var nodeIndex = node.Index;
                    if (nodeIndex != root.Index && level[nodeIndex] == 0)
                    {
                        parent[nodeIndex] = order[i];
                        level[nodeIndex]  = level[order[i]] + 1;
                        order[j++]        = nodeIndex;
                    }
                }
            }

            topologicalOrder = new RootedTreeNode[n];
            for (int i = n - 1; i >= 0; i--)
            {
                var nodeIndex = order[i];
                topologicalOrder[i] = new RootedTreeNode(this, graph.GetNode(nodeIndex), parent[nodeIndex], level[nodeIndex]);
            }

            Root = topologicalOrder[0];
        }
Пример #4
0
        public void TestTreeLCA()
        {
            Random r = new Random(0);

            for (int i = 0; i < 10; i++)
            {
                int   N    = r.Next(30000, 40000);
                int[] perm = new int[N];
                for (int j = 0; j < N; j++)
                {
                    perm[j] = j;
                }
                for (int j = 0; j < N; j++)
                {
                    int swap = j + r.Next(N - j);
                    int tmp  = perm[j];
                    perm[j]    = perm[swap];
                    perm[swap] = tmp;
                }

                Graph g = new Graph(N);
                for (int j = 1; j < N; j++)
                {
                    int a = r.Next(j);
                    g.AddEdge(perm[a], perm[j]);
                }
                RootedTree tree = new RootedTree(g, g.GetNode(perm[0]));

                for (int j = 0; j < 100; j++)
                {
                    int            a = r.Next(N), b = r.Next(N);
                    RootedTreeNode p = tree.GetNode(a), q = tree.GetNode(b);

                    // Naive solution
                    var pp = p;
                    var qq = q;
                    List <RootedTreeNode> ptrail = new List <RootedTreeNode>(), qtrail = new List <RootedTreeNode>();
                    while (pp != null)
                    {
                        ptrail.Add(pp);
                        pp = pp.Parent;
                    }
                    while (qq != null)
                    {
                        qtrail.Add(qq);
                        qq = qq.Parent;
                    }
                    ptrail.Reverse();
                    qtrail.Reverse();
                    int k = 0;
                    while (k + 1 < ptrail.Count && k + 1 < qtrail.Count && ptrail[k + 1] == qtrail[k + 1])
                    {
                        k++;
                    }
                    RootedTreeNode expected = ptrail[k];

                    RootedTreeNode lca = tree.GetLowestCommonAncestor(p, q);

                    Assert.AreSame(expected, lca);
                }
            }
        }
Пример #5
0
 internal void SetNode(RootedTreeNode treeNode)
 {
     RootedTreeNodes[treeNode.Node.Index] = treeNode;
 }