Example #1
0
        /// <summary>
        /// Reconstruct the calculated tree, by backtracking the results
        /// </summary>
        /// <param name="graph"></param>
        public static void ConstructTreeDepthTree(SubGraph graph)
        {
            if (graph.size == 1)
            {
                return;
            }

            short currentNode = (short)(_table[graph.nodes] >> 16);

            BitArray newNodes = new BitArray(graph.nodes)
            {
                [currentNode] = false
            };

            foreach (SubGraph cc in ConnectedComponents(currentNode, newNodes))
            {
                // Leafs aren't saved in the table.
                if (cc.size == 1)
                {
                    _nodeLocations[FirstNode(cc.nodes)] = (short)(currentNode + 1);
                    continue;
                }

                if (IsTree(cc))
                {
                    // Path is a special type of tree
                    // Paths require a different reconstruction
                    if (IsPath(cc.nodes))
                    {
                        ConstructPath(cc.size, cc.nodes, currentNode);
                        continue;
                    }

                    short treeRoot = _adjacencyList[currentNode].Find(v => cc.nodes[v]);
                    _nodeLocations[treeRoot] = (short)(currentNode + 1);
                    ConstructSubTree(CreateTree(cc.nodes, treeRoot), _treeRanks[cc.nodes]);
                    continue;
                }

                _nodeLocations[_table[cc.nodes] >> 16] = (short)(currentNode + 1);
                ConstructTreeDepthTree(cc);
            }
        }
Example #2
0
 /// <summary>
 /// Check if a sub-graph is a tree
 /// </summary>
 /// <param name="graph">The input graph.<br /> NOTE: This has to be a connected graph.</param>
 /// <returns></returns>
 private static bool IsTree(SubGraph graph)
 {
     // Check if the graph of n vertices has n - 1 edges.
     return(graph.edges == graph.size - 1);
 }
Example #3
0
        public static void Main(string[] args)
        {
#if DEBUG
            // Try to load file when needed
            if (args != null && args.Length > 0)
            {
                StreamReader inputFile;
                using (inputFile = new StreamReader(args[0])) {
                    Console.SetIn(inputFile);
                }
            }
#endif

            // Load the graph
            ReadGraph();

            // Fill nodes by degree array and sort
            _nodesByDegree = new short[_graphSize];
            for (short i = 0; i < _graphSize; i++)
            {
                _nodesByDegree[i] = i;
            }
            // Sort the nodes by degree
            Array.Sort(_nodesByDegree, (n1, n2) => _adjacencyList[n2].Count.CompareTo(_adjacencyList[n1].Count));

            // Init memorization 'array'
            _table = new Dictionary <BitArray, int>(new BitArrayEqualityComparer());
            // Init tree ranks dictionary
            _treeRanks = new Dictionary <BitArray, short[]>(new BitArrayEqualityComparer());

            // Run solver
            SubGraph fullGraph = new SubGraph(
                new BitArray(_graphSize, true),
                _graphSize,
                _graphEdges,
                1
                );

            // Try if a tree-depth below a certain number can be found.
            short currentTry = (short)(Math.Floor(Math.Log(fullGraph.size, 2)) + 2);

            int result = 0;
            _table[fullGraph.nodes] = short.MaxValue;
            while ((_table[fullGraph.nodes] & 0xFFFF) == short.MaxValue)
            {
                // Try to get the tree-depth
                result = TreeDepth(fullGraph, currentTry);

                // Increase the current try
                currentTry = (short)(currentTry * 1.5);
            }

            // Reconstruct tree
            _nodeLocations = new short[_graphSize];
            ConstructTreeDepthTree(fullGraph);

            // Write the results
            Console.WriteLine(result);
            foreach (short node in _nodeLocations)
            {
                Console.WriteLine(node);
            }

#if DEBUG
            Console.ReadLine();
#endif
        }
Example #4
0
        public static int TreeDepth(SubGraph graph, short bestResult = short.MaxValue, short from = -1)
        {
            if (_table.ContainsKey(graph.nodes))
            {
                int res = _table[graph.nodes];
                if ((res & 0xFFFF) < short.MaxValue ||
                    (res >> 16) >= bestResult
                    )
                {
                    return(res & 0xFFFF);
                }
            }

            // Graph is just a single node
            if (graph.size == 1)
            {
                return(1);
            }

            // Graph is a tree
            if (IsTree(graph))
            {
                int log = (int)Math.Log(graph.size, 2) + 1;
                if (log > bestResult)
                {
                    return(short.MaxValue);
                }

                // A path is special type of tree
                if (IsPath(graph.nodes))                   // Graph is a path
                {
                    return(log);
                }

                // Graph is not a path, but still a tree.

                // Find a root for the tree
                short treeRoot = _adjacencyList[from].Find(v => graph.nodes[v]);
                // Create the space to write the ranks to
                short[] treeRank = new short[_graphSize];
                // Set the tree-ranks list
                _treeRanks[graph.nodes] = treeRank;
                // Get rank of the tree
                int rank = CriticalRankTree(CreateTree(graph.nodes, treeRoot), treeRank).GetMax();
                // Save the rank to the table
                _table[graph.nodes] = (from << 16) | rank;
                // Return the rank
                return(rank);
            }

            // The current best result
            // NOTE: The tree-depth cannot be bigger than the amount of nodes in the graph.
            int result = Math.Min(bestResult, graph.size);
            // The root that we chose to achieve this result
            int root = -1;

            foreach (short i in _nodesByDegree)
            {
                if (!graph.nodes[i])
                {
                    continue;
                }

                // Remove node i from the graph
                BitArray newNodes = new BitArray(graph.nodes)
                {
                    [i] = false
                };

                int size = 0;
                // Go through connected components
                foreach (SubGraph cc in ConnectedComponents(i, newNodes))
                {
                    // The tree-depth if the component has te be at least the size of
                    // a path that it contains.
                    if (result < (short)Math.Log(cc.pathSize, 2) + 1)
                    {
                        size = short.MaxValue;
                        break;
                    }

                    // NOTE: The current value of 'result' is our best solution yet
                    int td = TreeDepth(cc, (short)(result - 1), i);

                    // ReSharper disable once InvertIf
                    if (td > size)
                    {
                        size = td;

                        // If the current tree-depth is also bigger than our best result yet,
                        // it is better to break the branch.
                        if (td >= result)
                        {
                            break;
                        }
                    }
                }
                // Add the current node to the size
                size += 1;

                // ReSharper disable once InvertIf
                if (size <= result)                   // Found a better result
                {
                    result = size;
                    root   = i;
                }
            }


            if (root == -1)
            {
                // Set the root as the best result used to get this result
                root   = result;
                result = short.MaxValue;
            }

            _table[graph.nodes] = (root << 16) | result;
            // Return the result
            return(result);
        }