Beispiel #1
0
        /// <summary>
        /// Checks all properties of the specified tree for correctness.
        /// </summary>
        /// <typeparam name="TKey">Type of keys.</typeparam>
        /// <typeparam name="TValue">Type of values.</typeparam>
        /// <param name="tree">Specified tree.</param>
        /// <param name="elements">Expected elements in the tree.</param>
        /// <param name="isMulti">True if testing the multi-dictionary scenario.</param>
        private static void CheckTree <TKey, TValue>(LeftLeaningRedBlackTree <TKey, TValue> tree, List <KeyValuePair <TKey, TValue> > elements, bool isMulti) where TKey : IComparable
        {
            // Check count and keys
            Assert.AreEqual(elements.Count, tree.Count);
            List <TKey> sortedKeys     = elements.Select(e => e.Key).Distinct().OrderBy(k => k).ToList();
            List <TKey> binaryTreeKeys = tree.GetKeys().ToList();

            Assert.AreEqual(sortedKeys.Count, binaryTreeKeys.Count);

            // Check key values
            for (int i = 0; i < sortedKeys.Count; i++)
            {
                Assert.AreEqual(sortedKeys[i], binaryTreeKeys[i]);
                List <TValue> sortedKeyValues     = elements.Where(e => 0 == e.Key.CompareTo(sortedKeys[i])).Select(e => e.Value).OrderBy(v => v).ToList();
                List <TValue> binaryTreeKeyValues = tree.GetValuesForKey(sortedKeys[i]).ToList();
                Assert.AreEqual(sortedKeyValues.Count, binaryTreeKeyValues.Count);
                for (int j = 0; j < sortedKeyValues.Count; j++)
                {
                    Assert.AreEqual(sortedKeyValues[j], binaryTreeKeyValues[j]);
                }
                if (!isMulti)
                {
                    Assert.AreEqual(tree.GetValueForKey(sortedKeys[i]), binaryTreeKeyValues.Single());
                }
            }

            // Check values
            List <TValue> sortedValues     = sortedKeys.SelectMany(k => elements.Where(e => 0 == e.Key.CompareTo(k)).Select(e => e.Value).OrderBy(v => v)).ToList();
            List <TValue> binaryTreeValues = tree.GetValuesForAllKeys().ToList();

            Assert.AreEqual(sortedValues.Count, binaryTreeValues.Count);
            for (int i = 0; i < sortedValues.Count; i++)
            {
                Assert.AreEqual(sortedValues[i], binaryTreeValues[i]);
            }

            // Check additional properties
            if (0 < elements.Count)
            {
                Assert.AreEqual(sortedKeys[0], tree.MinimumKey);
                Assert.AreEqual(sortedKeys[sortedKeys.Count - 1], tree.MaximumKey);
                Assert.AreEqual(sortedValues[0], tree.MinimumValue);
                Assert.AreEqual(sortedValues[sortedValues.Count - 1], tree.MaximumValue);
            }
        }
Beispiel #2
0
        public static ulong Solve(int n, int[][] edges, ulong[] coins)
        {
            if (n == 1)
            {
                return(ulong.MaxValue);
            }

            var adj  = ToDirectedTree(edges, n + 1);
            var head = edges[0][0];

            var sumsBelow = new ulong[n + 1];

            var stack      = new Stack <int>(n + 1);
            var ignoreSums = new bool[n + 1];

            foreach (var node in Traverse_Tree_PostOrder_NonRec(head, v => adj[v]))
            {
                sumsBelow[node] = coins[node - 1] + adj[node].Select(v => sumsBelow[v]).Sum();
            }

            var total = sumsBelow[head];

            var sumsSet = new LeftLeaningRedBlackTree <ulong, int>((x, y) => x.CompareTo(y), (x, y) => x.CompareTo(y));

            for (var i = 1; i <= n; i++)
            {
                sumsSet.Add(sumsBelow[i], i);
            }

            var best = ulong.MaxValue;

            var path = new List <int>(n + 1)
            {
                head
            };
            var notInA = new bool[n + 1];

            notInA[head] = true;

            foreach (var edgeInfo in Traverse_Dfs_WithEvents(head, v => adj[v]))
            {
                var aNode = edgeInfo.Child;

                if (edgeInfo.IsDownNotUp)
                {
                    path.Add(aNode);

                    notInA[edgeInfo.Parent] = true;
                    foreach (var otherChild in adj[edgeInfo.Parent])
                    {
                        if (otherChild != edgeInfo.Child)
                        {
                            foreach (var node in Traverse_Tree_Dfs(otherChild, v => adj[v], stack))
                            {
                                notInA[node] = true;
                            }
                        }
                    }
                }
                else
                {
                    path.RemoveAt(path.Count - 1);

                    notInA[edgeInfo.Parent] = false;
                    foreach (var otherChild in adj[edgeInfo.Parent])
                    {
                        if (otherChild != edgeInfo.Child)
                        {
                            foreach (var node in Traverse_Tree_Dfs(otherChild, v => adj[v], stack))
                            {
                                notInA[node] = false;
                            }
                        }
                    }

                    continue;
                }

                var a = sumsBelow[aNode];

                if (a == total - a)
                {
                    best = Math.Min(best, a);
                }

                foreach (var pathNode in path)
                {
                    if (pathNode != aNode)
                    {
                        var sum = sumsBelow[pathNode];
                        sumsSet.Remove(sum, pathNode);
                        sumsSet.Add(sum - a, pathNode);
                    }
                }

                var searchme = new List <ulong>(3)
                {
                    a
                };
                if (total > 2 * a)
                {
                    searchme.Add(total - 2 * a);
                }
                if (total != a && (total - a) % 2 == 0)
                {
                    searchme.Add((total - a) / 2);
                }

                foreach (var sum in searchme)
                {
                    if (sumsSet.GetValuesForKey(sum).Any(i => notInA[i]))
                    {
                        best = CalcBest(best, a, sum, total - a - sum);
                    }
                }

                foreach (var pathNode in path)
                {
                    if (pathNode != aNode)
                    {
                        var sum = sumsBelow[pathNode];
                        sumsSet.Remove(sum - a, pathNode);
                        sumsSet.Add(sum, pathNode);
                    }
                }
            }

            return(best);
        }