public void RerootingTestABC160ExampleF()
        {
            var inputs = @"8
1 2
2 3
3 4
3 5
3 6
6 7
6 8".Split(Environment.NewLine);

            var n     = int.Parse(inputs[0]);
            var graph = new BasicGraph(n);

            foreach (var input in inputs.Skip(1).Select(s => s.Split(' ').Select(s => int.Parse(s) - 1).ToArray()))
            {
                graph.AddEdge(input[0], input[1]);
                graph.AddEdge(input[1], input[0]);
            }

            var rerooting = new Rerooting <BasicEdge, DPState>(graph);
            var result    = rerooting.Solve().Select(r => r.Count.Value);

            var expected = new int[] { 40, 280, 840, 120, 120, 504, 72, 72 };

            Assert.Equal(expected, result);
        }
Beispiel #2
0
        public override void Solve(IOManager io)
        {
            var n    = io.ReadInt();
            var tree = new BasicGraph(n);

            for (int i = 0; i < n - 1; i++)
            {
                var u = io.ReadInt();
                var v = io.ReadInt();
                u--;
                v--;
                tree.AddEdge(u, v);
                tree.AddEdge(v, u);
            }

            var lca = new LowestCommonAncester(tree);

            var queries = io.ReadInt();

            for (int q = 0; q < queries; q++)
            {
                var a = io.ReadInt() - 1;
                var b = io.ReadInt() - 1;
                io.WriteLine(lca.Depths[a] + lca.Depths[b] - 2 * lca.Depths[lca.GetLcaNode(a, b)] + 1);
            }
        }
Beispiel #3
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var nodeCount = inputStream.ReadInt();

            tree    = new BasicGraph(nodeCount);
            counts  = new int[nodeCount];
            results = new int[nodeCount];

            for (int i = 0; i < nodeCount - 1; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                counts[a]++;
                counts[b]++;
                tree.AddEdge(new BasicEdge(a, b));
                tree.AddEdge(new BasicEdge(b, a));
            }

            points = new Queue <int>(inputStream.ReadIntArray().OrderBy(i => i));
            var total = points.Take(points.Count - 1).Sum();

            Bfs();

            yield return(total);

            yield return(results.Join(' '));
        }
Beispiel #4
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            Modular.InitializeCombinationTable();
            var nodesCount = inputStream.ReadInt();

            graph = new BasicGraph(nodesCount);

            for (int i = 0; i < nodesCount - 1; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
            }

            dpStates = new DPState[nodesCount];

            for (int i = 0; i < dpStates.Length; i++)
            {
                dpStates[i] = new DPState(new Modular(1), 0);
            }

            var rerooting = new Rerooting <BasicNode, BasicEdge, DPState>(graph);
            var results   = rerooting.Solve().Select(r => r.Count.Value);

            foreach (var result in results)
            {
                yield return(result);
            }
        }
Beispiel #5
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var n = inputStream.ReadInt();

            maxValues = Enumerable.Repeat(int.MaxValue, n).ToArray();
            minValues = Enumerable.Repeat(int.MinValue, n).ToArray();

            graph = new BasicGraph(n);
            for (int i = 0; i < n - 1; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
            }

            var starts = new List <int>();
            var k      = inputStream.ReadInt();

            for (int i = 0; i < k; i++)
            {
                var(v, p) = inputStream.ReadValue <int, int>();
                v--;
                maxValues[v] = p;
                minValues[v] = p;
                starts.Add(v);
            }

            if (!CheckEvenOdd(starts[0], -1, minValues[starts[0]]))
            {
                yield return("No");

                yield break;
            }

            //Shuffle(starts);

            foreach (var start in starts)
            {
                Dfs(start, -1, maxValues[start] + 1, minValues[start] - 1);
            }

            for (int i = 0; i < maxValues.Length; i++)
            {
                if (maxValues[i] < minValues[i])
                {
                    yield return("No");

                    yield break;
                }
            }

            yield return("Yes");

            foreach (var value in minValues)
            {
                yield return(value);
            }
        }
Beispiel #6
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var(nodeCount, takahashiStart, aokiStart) = inputStream.ReadValue <int, int, int>();
            takahashiStart--;
            aokiStart--;
            var tree = new BasicGraph(nodeCount);

            for (int i = 0; i < nodeCount - 1; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                tree.AddEdge(new BasicEdge(a, b));
                tree.AddEdge(new BasicEdge(b, a));
            }

            var takahashiDistances = GetDistances(takahashiStart);
            var aokiDistances      = GetDistances(aokiStart);

            var result = 0;

            for (int i = 0; i < nodeCount; i++)
            {
                if (takahashiDistances[i] < aokiDistances[i])
                {
                    result = Math.Max(result, aokiDistances[i]);
                }
            }

            yield return(result - 1);

            int[] GetDistances(int startNode)
            {
                const int Inf       = 1 << 28;
                var       todo      = new Queue <int>();
                var       distances = Enumerable.Repeat(Inf, nodeCount).ToArray();

                todo.Enqueue(startNode);
                distances[startNode] = 0;

                while (todo.Count > 0)
                {
                    var current = todo.Dequeue();
                    foreach (var edge in tree[current])
                    {
                        var next = edge.To.Index;
                        if (distances[next] == Inf)
                        {
                            distances[next] = distances[current] + 1;
                            todo.Enqueue(next);
                        }
                    }
                }

                return(distances);
            }
        }
Beispiel #7
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            const int A = 0;
            const int B = 1;

            var(nodeCount, edgeCount) = inputStream.ReadValue <int, int>();
            var s = inputStream.ReadLine().Select(c => c == 'A' ? A : B).ToArray();

            var graph     = new BasicGraph(nodeCount);
            var adjacents = new int[nodeCount, B + 1];

            for (int i = 0; i < edgeCount; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                adjacents[a, s[b]]++;
                adjacents[b, s[a]]++;
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
            }

            var queue  = new Queue <int>();
            var erased = new bool[nodeCount];

            for (int i = 0; i < nodeCount; i++)
            {
                if (adjacents[i, A] == 0 || adjacents[i, B] == 0)
                {
                    queue.Enqueue(i);
                    erased[i] = true;
                }
            }

            while (queue.Count > 0)
            {
                var current = queue.Dequeue();
                foreach (var edge in graph[current])
                {
                    var next = edge.To.Index;
                    if (!erased[next])
                    {
                        adjacents[next, s[current]]--;
                        if (adjacents[next, A] == 0 || adjacents[next, B] == 0)
                        {
                            erased[next] = true;
                            queue.Enqueue(next);
                        }
                    }
                }
            }

            yield return(erased.Any(b => !b) ? "Yes" : "No");
        }
Beispiel #8
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var(nodeCount, edgeCount) = inputStream.ReadValue <int, int>();

            if (nodeCount - 1 == edgeCount)
            {
                yield return(0);

                yield break;
            }

            var graph = new BasicGraph(nodeCount);

            for (int i = 0; i < edgeCount; i++)
            {
                var(x, y) = inputStream.ReadValue <int, int>();
                graph.AddEdge(new BasicEdge(x, y));
                graph.AddEdge(new BasicEdge(y, x));
            }

            var groups = Enumerable.Repeat(-1, nodeCount).ToArray();

            void Dfs(int current, int parent, int groupNumber)
            {
                groups[current] = groupNumber;
                foreach (var edge in graph[current])
                {
                    var next = edge.To.Index;
                    if (next == parent || groups[next] != -1)
                    {
                        continue;
                    }

                    Dfs(next, current, groupNumber);
                }
            }

            var groupCount = 0;

            for (int i = 0; i < nodeCount; i++)
            {
                if (groups[i] == -1)
                {
                    Dfs(i, -1, groupCount++);
                }
            }

            for (int i = 0; i < nodeCount; i++)
            {
            }
        }
Beispiel #9
0
        public override void Solve(IOManager io)
        {
            var nodeCount = io.ReadInt();
            var edgeCount = io.ReadInt();

            var graph     = new BasicGraph(nodeCount);
            var indegrees = new int[graph.NodeCount];

            for (int i = 0; i < edgeCount; i++)
            {
                var s = io.ReadInt();
                var t = io.ReadInt();
                s--;
                t--;

                graph.AddEdge(s, t);
                indegrees[t]++;
            }

            var result = double.MaxValue;

            for (int block = 0; block < graph.NodeCount; block++)
            {
                result.ChangeMin(GetExpectation(block));
            }

            io.WriteLine(result);

            double GetExpectation(int block)
            {
                Span <double> dp = stackalloc double[graph.NodeCount];

                dp[^ 1] = 0;
Beispiel #10
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var nodeCount = inputStream.ReadInt();
            var a         = inputStream.ReadIntArray();
            var graph     = new BasicGraph(nodeCount);

            for (int i = 0; i < nodeCount - 1; i++)
            {
                var(u, v) = inputStream.ReadValue <int, int>();
                u--;
                v--;
                graph.AddEdge(new BasicEdge(u, v));
                graph.AddEdge(new BasicEdge(v, u));
            }

            var dp      = Enumerable.Repeat(int.MaxValue, nodeCount).ToArray();
            var results = new int[nodeCount];

            void Dfs(int current, int parent)
            {
                var index = SearchExtensions.GetGreaterEqualIndex(dp, a[current]);
                var last  = dp[index];

                dp[index]        = a[current];
                results[current] = SearchExtensions.GetLessThanIndex(dp, int.MaxValue);

                foreach (var edge in graph[current])
                {
                    var next = edge.To.Index;
                    if (next != parent)
                    {
                        Dfs(next, current);
                    }
                }

                dp[index] = last;
            }

            Dfs(0, -1);

            for (int i = 0; i < results.Length; i++)
            {
                yield return(results[i] + 1);
            }
        }
Beispiel #11
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var n = inputStream.ReadInt();

            tree = new BasicGraph(n);
            for (int i = 0; i < n - 1; i++)
            {
                var(x, y) = inputStream.ReadValue <int, int>();
                x--;
                y--;
                tree.AddEdge(new BasicEdge(x, y));
                tree.AddEdge(new BasicEdge(y, x));
            }

            var(whites, blacks) = Dfs(0, -1);

            yield return(whites + blacks);
        }
Beispiel #12
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var n = inputStream.ReadInt();

            graph = new BasicGraph(n);
            for (int i = 0; i < n - 1; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
            }

            var painter = new Painter(graph);
            var count   = painter.Search(new BasicNode(0));

            yield return((count[0, 0] + count[0, 1]).Value);
        }
Beispiel #13
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var n = inputStream.ReadInt();

            tree = new BasicGraph(n);
            for (int i = 0; i < n - 1; i++)
            {
                var(x, y) = inputStream.ReadValue <int, int>();
                x--;
                y--;
                tree.AddEdge(new BasicEdge(x, y));
                tree.AddEdge(new BasicEdge(y, x));
            }

            depthAndIndices = new List <DepthAndIndex>();
            firstIndices    = new int[n];
            depthes         = new int[n];

            EularTour(new BasicNode(0), new BasicNode(-1), 0);
            var segTree = new SegmentTree <DepthAndIndex>(depthAndIndices);

            var queries = inputStream.ReadInt();

            for (int q = 0; q < queries; q++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;

                var indexA = firstIndices[a];
                var indexB = firstIndices[b];
                if (indexA > indexB)
                {
                    (indexA, indexB) = (indexB, indexA);
                }
                var lca = segTree.Query(indexA, indexB + 1).Index;
                yield return(depthes[a] + depthes[b] - 2 * depthes[lca] + 1);
            }
        }
Beispiel #14
0
        public override void Solve(IOManager io)
        {
            var nodes = io.ReadInt();
            var graph = new BasicGraph(nodes);

            for (int i = 0; i < nodes - 1; i++)
            {
                var a = io.ReadInt() - 1;
                var b = io.ReadInt() - 1;
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
            }

            var costs = io.ReadIntArray(nodes);

            Array.Sort(costs, (a, b) => b - a);

            var queue   = new Queue <int>(costs);
            var results = new int[nodes];

            Dfs(0, -1);

            io.WriteLine(costs.Sum() - costs.Max());
            io.WriteLine(results, ' ');

            void Dfs(int current, int parent)
            {
                results[current] = queue.Dequeue();
                foreach (var edge in graph[current])
                {
                    var next = edge.To.Index;
                    if (next != parent)
                    {
                        Dfs(next, current);
                    }
                }
            }
        }
Beispiel #15
0
        public override void Solve(IOManager io)
        {
            Modular.InitializeCombinationTable();
            var n    = io.ReadInt();
            var tree = new BasicGraph(n);

            for (int i = 0; i < n - 1; i++)
            {
                var a = io.ReadInt() - 1;
                var b = io.ReadInt() - 1;
                tree.AddEdge(a, b);
                tree.AddEdge(b, a);
            }

            var rerooting = new Rerooting <BasicEdge, CountAndWay>(tree);

            var results = rerooting.Solve();

            foreach (var r in results)
            {
                io.WriteLine(r.Way);
            }
        }
Beispiel #16
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            Modular.InitializeCombinationTable();
            var nodeCount = inputStream.ReadInt();
            var graph     = new BasicGraph(nodeCount);

            for (int i = 0; i < nodeCount - 1; i++)
            {
                var(u, v) = inputStream.ReadValue <int, int>();
                u--;
                v--;
                graph.AddEdge(new BasicEdge(u, v));
                graph.AddEdge(new BasicEdge(v, u));
            }

            var rerooting = new Rerooting <BasicNode, BasicEdge, CountAndWay>(graph);
            var results   = rerooting.Solve();

            foreach (var result in results)
            {
                yield return(result.Way);
            }
        }
Beispiel #17
0
        public static BasicGraph Do(string filePath)
        {
            Console.WriteLine("Reading file {0}", filePath);

            if (!File.Exists(filePath))
            {
                throw new Exception(string.Format("File {0} does not exist. Will not continue.", filePath));
            }

            var lines = File.ReadAllLines(filePath);

            var index = 0;
            var graph = new BasicGraph();

            foreach (var line in lines)
            {
                index++;

                if (string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }

                Console.WriteLine("Parsing line {0}.", index);

                var triplet = line.Split(',').Select(x => x.Trim()).ToList();

                if (triplet.Count() != 3)
                {
                    Console.WriteLine(" Invalid format, skipping.");
                    continue;
                }

                var    left  = triplet[0];
                var    right = triplet[1];
                double weight;

                if (!Double.TryParse(triplet[2], out weight))
                {
                    Console.WriteLine(" Could not parse weight, skipping.");
                    continue;
                }

                Console.WriteLine(" Parsed Edge {0}<->{1} with a weight of {2}", left, right, weight);
                graph.AddEdge(left, right, weight);
            }

            Console.WriteLine("Parsing complete.");
            return(graph);
        }
Beispiel #18
0
        public override void Solve(IOManager io)
        {
            var n      = io.ReadInt();
            var x      = io.ReadInt() - 1;
            var tree   = new BasicGraph(n);
            var jewels = io.ReadIntArray(n).Select(b => b == 1).ToArray();

            for (int i = 0; i < n - 1; i++)
            {
                var a = io.ReadInt();
                var b = io.ReadInt();
                a--;
                b--;
                tree.AddEdge(a, b);
                tree.AddEdge(b, a);
            }

            Dfs(x, -1);

            io.WriteLine(Math.Max((jewels.Count(b => b) - 1) * 2, 0));

            bool Dfs(int current, int parent)
            {
                var hasJewel = jewels[current];

                foreach (var next in tree[current])
                {
                    if (parent != next)
                    {
                        hasJewel |= Dfs(next, current);
                    }
                }

                return(jewels[current] = hasJewel);
            }
        }
Beispiel #19
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var(n, m) = inputStream.ReadValue <int, int>();
            var heights = inputStream.ReadIntArray();
            var graph   = new BasicGraph(n);

            for (int i = 0; i < m; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
            }

            var count = 0;

            for (int i = 0; i < heights.Length; i++)
            {
                var ok = true;
                foreach (var edge in graph[i])
                {
                    var to = edge.To.Index;
                    if (heights[i] <= heights[to])
                    {
                        ok = false;
                    }
                }
                if (ok)
                {
                    count++;
                }
            }

            yield return(count);
        }
Beispiel #20
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var(nodeCount, edgeCount) = inputStream.ReadValue <int, int>();
            graph  = new BasicGraph(nodeCount);
            colors = new Color[nodeCount];

            for (int i = 0; i < edgeCount; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
            }

            if (Paint())
            {
                yield return((long)colors.Count(c => c == Color.Black) * colors.Count(c => c == Color.White) - edgeCount);
            }
            else
            {
                yield return((long)nodeCount * (nodeCount - 1) / 2 - edgeCount);
            }
        }
Beispiel #21
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var(rooms, paths) = inputStream.ReadValue <int, int>();
            var dungeon = new BasicGraph(rooms);

            for (int i = 0; i < paths; i++)
            {
                var(a, b) = inputStream.ReadValue <int, int>();
                a--;
                b--;
                dungeon.AddEdge(new BasicEdge(a, b));
                dungeon.AddEdge(new BasicEdge(b, a));
            }

            var solver   = new BfsSolver(dungeon);
            var previous = solver.Search(new BasicNode(0));

            yield return("Yes");

            for (int i = 1; i < previous.Length; i++)
            {
                yield return(previous[i] + 1);
            }
        }
Beispiel #22
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var n = inputStream.ReadInt();

            graph = new BasicGraph(n);

            for (int me = 1; me < n; me++)
            {
                var hostile = inputStream.ReadInt();
                hostile--;
                graph.AddEdge(new BasicEdge(hostile, me));
            }

            yield return(Dfs(0));
        }
Beispiel #23
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var(n, m) = inputStream.ReadValue <int, int>();
            var edges         = new BasicEdge[n - 1 + m];
            var graph         = new BasicGraph(n);
            var inDegrees     = new int[n];
            var invertedGraph = new BasicGraph(n);

            for (int i = 0; i < edges.Length; i++)
            {
                var(from, to) = inputStream.ReadValue <int, int>();
                from--;
                to--;
                var edge = new BasicEdge(from, to);
                edges[i] = edge;
                inDegrees[to]++;
                graph.AddEdge(edge);
                invertedGraph.AddEdge(new BasicEdge(to, from));
            }

            var sortedNodes          = TopologicalSort(graph, inDegrees);
            var sortedNodesPositions = new int[n];

            for (int i = 0; i < sortedNodesPositions.Length; i++)
            {
                var node = sortedNodes[i];
                sortedNodesPositions[node] = i;
            }

            for (int i = 0; i < n; i++)
            {
                var parents        = invertedGraph[i].ToArray();
                var answer         = -1;
                var answerPosition = -1;

                foreach (var parent in parents)
                {
                    var position = sortedNodesPositions[parent.To.Index];
                    if (answerPosition < position)
                    {
                        answerPosition = position;
                        answer         = parent.To.Index;
                    }
                }

                yield return(answer + 1);
            }
        }
Beispiel #24
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var n         = inputStream.ReadInt();
            var graph     = new BasicGraph(n * n);
            var indegrees = new int[graph.NodeCount];

            for (int me = 0; me < n; me++)
            {
                var enemies = inputStream.ReadIntArray().Select(i => i - 1);
                var last    = -1;
                foreach (var enemy in enemies)
                {
                    if (last != -1)
                    {
                        var from = GetIndex(me, last, n);
                        var to   = GetIndex(me, enemy, n);
                        graph.AddEdge(new BasicEdge(from, to));
                        indegrees[to]++;
                    }
                    last = enemy;
                }
            }

            var sorted = TopologicalSort(graph, indegrees);

            if (sorted == null)
            {
                yield return(-1);
            }
            else
            {
                var dp = new int[sorted.Count];
                foreach (var currentNode in sorted)
                {
                    foreach (var next in graph[currentNode])
                    {
                        UpdateWhenLarge(ref dp[next.To.Index], dp[currentNode] + 1);
                    }
                }
                var max = dp.Max() + 1;
                yield return(max);
            }
        }
Beispiel #25
0
        public override void Solve(IOManager io)
        {
            var n    = io.ReadInt();
            var tree = new BasicGraph(n);
            var root = -1;

            for (int i = 0; i < n; i++)
            {
                var p = io.ReadInt();

                if (p == -1)
                {
                    root = i;
                }
                else
                {
                    p--;
                    tree.AddEdge(p, i);
                }
            }

            var lca = new LowestCommonAncester(tree, root);

            var queries = io.ReadInt();

            for (int q = 0; q < queries; q++)
            {
                var staff = io.ReadInt() - 1;
                var boss  = io.ReadInt() - 1;

                if (lca.GetLcaNode(staff, boss) == boss)
                {
                    io.WriteLine("Yes");
                }
                else
                {
                    io.WriteLine("No");
                }
            }
        }
Beispiel #26
0
        public override IEnumerable <object> Solve(TextReader inputStream)
        {
            var n = inputStream.ReadInt();

            tree = new BasicGraph(n);
            if (n == 1)
            {
                yield return("POSSIBLE");

                yield break;
            }

            var p = inputStream.ReadIntArray().Select(pi => pi - 1).ToArray();

            x = inputStream.ReadIntArray();

            for (int i = 0; i < p.Length; i++)
            {
                var me = i + 1;
                tree.AddEdge(new BasicEdge(p[i], me));
            }

            yield return(Dfs(0) != Sum.NG ? "POSSIBLE" : "IMPOSSIBLE");
        }
Beispiel #27
0
        public override void Solve(IOManager io)
        {
            var n     = io.ReadInt();
            var graph = new BasicGraph(n);

            var degrees = new int[n];

            for (int i = 0; i < n - 1; i++)
            {
                var a = io.ReadInt();
                var b = io.ReadInt();
                graph.AddEdge(new BasicEdge(a, b));
                graph.AddEdge(new BasicEdge(b, a));
                degrees[a]++;
                degrees[b]++;
            }

            for (int i = 0; i < degrees.Length; i++)
            {
                if (degrees[i] > 2)
                {
                    var result = Dfs(i, -1);
                    io.WriteLine(result);
                    return;
                }
            }

            io.WriteLine(1);

            int Dfs(int current, int parent)
            {
                var children        = 0;
                var antennas        = 0;
                var antennaBranches = 0;

                foreach (var edge in graph[current])
                {
                    var next = edge.To.Index;
                    if (next == parent)
                    {
                        continue;
                    }

                    children++;
                    var an = Dfs(next, current);
                    antennas += an;

                    if (an > 0)
                    {
                        antennaBranches++;
                    }
                }

                if (children > antennaBranches + 1)
                {
                    antennas += children - (antennaBranches + 1);
                }

                return(antennas);
            }
        }
Beispiel #28
0
        protected override void PrepareSolution()
        {
            locationsToKeycodes = new Dictionary <string, uint>();
            locationsToKeycodes.Add("@", 0);
            for (int a = 0; a < alphabet.Length; a++)
            {
                locationsToKeycodes.Add(alphabet[a].ToString(), (uint)1 << a);
            }
            keycodesToLocations = locationsToKeycodes.ToDictionary((kvp) => kvp.Value, (kvp) => kvp.Key);
            locationsToKeycodes.Add("0", 0); //Making sure that only keys have non-zero values
            locationsToKeycodes.Add("1", 0);
            locationsToKeycodes.Add("2", 0);
            locationsToKeycodes.Add("3", 0);

            var stringTilesByRowAndColumn = mazeRows.Select(row => row.Select(tile => tile.ToString()));
            var maze           = new Maze <string>(stringTilesByRowAndColumn, "#", floors.Concat(keys).Select(tile => tile.ToString()));
            var floorsAndDoors = floors.Concat(doors).Select(tile => tile.ToString()).ToHashSet();

            maze.EliminateDeadEnds(floorsAndDoors, "#", walls.Select(tile => tile.ToString()).ToHashSet());

            var remainingKeysAndDoors = maze.GetAllTileTypes().ToHashSet();

            remainingKeysAndDoors.ExceptWith(new string[] { "@", ".", "#" });

            var quadRoots  = new Dictionary <string, (int, int)>();
            var centerTile = ((int x, int y))maze.FindFirstMatchingTile("@");

            maze[centerTile.x, centerTile.y] = "#";
            int intersectionCounter = 0;

            //Mark the corners around the center as intersections
            foreach (var direction in Direction.North.GetAll())
            {
                var(x, y) = DirectionHelper.NeighbourInDirection(direction, centerTile.x, centerTile.y);
                if (x == centerTile.x || y == centerTile.y)
                {
                    maze[x, y] = "#";
                }
                else
                {
                    maze[x, y] = intersectionCounter.ToString();
                    quadRoots.Add(intersectionCounter.ToString(), (x, y));
                    intersectionCounter++;
                }
            }

            var walkableTiles = floors.Concat(doors).Concat(keys).Select(tile => tile.ToString());

            //Do a floodfill of the remaining maze, changing the tile-type every time we encounter a door/key/intersection
            //tile-types will be built as follows [].[].[] where each[] is a door/key/intersection number

            var intersectionBranches = new HashSet <string>();

            var frontiers = new List <(int, int)>(quadRoots.Values);

            while (frontiers.Any())
            {
                var nextFrontiers = new List <(int, int)>();

                foreach (var(x, y) in frontiers)
                {
                    var currentTileType    = maze[x, y];
                    var relevantNeighbours = maze.GetNeighbours(x, y).Where(nb => walkableTiles.Contains(nb.Value));
                    var keysOrDoors        = relevantNeighbours.Where(nb => keys.Contains(nb.Value) || doors.Contains(nb.Value)).ToList();

                    if (relevantNeighbours.Count() > 1)
                    {
                        //this is an intersection an edge ends here, and 2 or 3 new edges start
                        maze[x, y] = $"{currentTileType}.";
                        int branchCounter = 0;
                        foreach (var nb in relevantNeighbours)
                        {
                            var(nbx, nby) = DirectionHelper.NeighbourInDirection(nb.Key, x, y);
                            var intersectionBranch = $"{currentTileType}.{intersectionCounter}:{branchCounter}";
                            maze[nbx, nby] = intersectionBranch;
                            branchCounter++;
                            nextFrontiers.Add((nbx, nby));
                            intersectionBranches.Add(intersectionBranch);
                        }
                        intersectionCounter++;
                    }
                    else
                    {
                        if (relevantNeighbours.Any())
                        {
                            var(nbx, nby)  = DirectionHelper.NeighbourInDirection(relevantNeighbours.First().Key, x, y);
                            maze[nbx, nby] = currentTileType;
                            nextFrontiers.Add((nbx, nby));
                        }
                    }

                    foreach (var nb in keysOrDoors)
                    {
                        //next tile will be a key or door, meaning the edge of this frontier will end there
                        var(nbx, nby) = DirectionHelper.NeighbourInDirection(nb.Key, x, y);
                        var updatedCurrentTileType = maze[nbx, nby];
                        maze[nbx, nby] = $"{updatedCurrentTileType}.{nb.Value}";
                    }
                }
                frontiers = nextFrontiers;
            }

            //intersections are marked by a . as final character, this means each branch has a count of 1 less than it should be
            var tileCounts = new Dictionary <string, int>(maze.GetTileCounts().Where(tc => tc.Value > 0 && tc.Key.Last() != '.'));

            foreach (var intersectionBranch in intersectionBranches)
            {
                tileCounts.TryGetValue(intersectionBranch, out int value);
                tileCounts[intersectionBranch] = value + 1;
            }

            //Build a graph
            graph = new BasicGraph();
            //Create nodes
            graph.AddNode("@");
            foreach (var(tile, count) in tileCounts)
            {
                var splitTile = tile.Split('.');
                var endpoint  = splitTile.Last().Split(':');
                if (!graph.ContainsNode(endpoint.First()))
                {
                    graph.AddNode(endpoint.First());
                }
            }

            keycodesToQuadrants = new Dictionary <uint, int>();
            //Create edges & blockingsets
            blockingsetPerKey = new Dictionary <uint, uint>();
            foreach (var(tile, _) in tileCounts)
            {
                var splitTile = tile.Split('.').Select(loc => loc.Split(':').First()).ToArray();
                if (splitTile.Length > 1)
                {
                    var from       = splitTile[splitTile.Length - 2];
                    var to         = splitTile[splitTile.Length - 1];
                    var lastPeriod = tile.LastIndexOf('.');
                    var edgeLength = tileCounts[tile.Substring(0, lastPeriod)];
                    graph.AddEdge(from, to, edgeLength);
                    if (keys.Contains(to))
                    {
                        var  blockingKeys = splitTile.Take(splitTile.Length - 1).Select(nodeName => nodeName.ToLower()).Where(keyName => keys.Contains(keyName)).Distinct();
                        uint blockingCode = 0;
                        foreach (var blockingKey in blockingKeys)
                        {
                            blockingCode = blockingCode | locationsToKeycodes[blockingKey];
                        }
                        blockingsetPerKey.Add(locationsToKeycodes[to], blockingCode);
                        keycodesToQuadrants.Add(locationsToKeycodes[to], int.Parse(splitTile.First()));
                    }
                }
            }

            //Add edges between @,0,1,2,3
            foreach (var quadrantStart in Enumerable.Range(0, 4).Select(q => q.ToString()))
            {
                graph.AddEdge("@", quadrantStart, 2);
            }
            graph.AddEdge("0", "1", 2);
            graph.AddEdge("1", "2", 2);
            graph.AddEdge("2", "3", 2);
            graph.AddEdge("3", "0", 2);
        }
Beispiel #29
0
        public override void Solve(IOManager io)
        {
            const string Inf              = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
            var          n                = io.ReadInt();
            var          edgeCount        = io.ReadInt();
            var          length           = io.ReadInt();
            var          originalCharList = new char[n];

            for (int i = 0; i < originalCharList.Length; i++)
            {
                originalCharList[i] = io.ReadChar();
            }

            var originalGraph = new Internal.SCCGraph(n);
            var edges         = new Edge[edgeCount];

            for (int i = 0; i < edges.Length; i++)
            {
                var a = io.ReadInt();
                var b = io.ReadInt();
                a--;
                b--;
                edges[i] = new Edge(a, b);
                originalGraph.AddEdge(a, b);
            }

            var(groupCount, ids) = originalGraph.SCCIDs();
            var graph = new BasicGraph(groupCount + 1);

            foreach (var(from, to) in edges)
            {
                if (ids[from] != ids[to])
                {
                    var contains = false;

                    foreach (var next in graph[ids[from] + 1])
                    {
                        contains |= next == ids[to] + 1;
                    }

                    if (!contains)
                    {
                        graph.AddEdge(ids[from] + 1, ids[to] + 1);
                    }
                }
            }

            for (int i = 1; i < graph.NodeCount; i++)
            {
                graph.AddEdge(0, i);
            }

            var dp = new string[graph.NodeCount, length + 1];

            dp.Fill(Inf);
            dp[0, 0] = "";

            var charList = Enumerable.Repeat(0, graph.NodeCount).Select(_ => new List <char>()).ToArray();

            for (int i = 0; i < originalCharList.Length; i++)
            {
                charList[ids[i] + 1].Add(originalCharList[i]);
            }

            foreach (var c in charList)
            {
                c.Sort();
            }

            for (int i = 0; i < graph.NodeCount; i++)
            {
                for (int l = 0; l <= length; l++)
                {
                    foreach (var next in graph[i])
                    {
                        var newString = dp[i, l];

                        if (newString == Inf)
                        {
                            continue;
                        }

                        ChangeMin(ref dp[next, l], newString);

                        for (int append = 0; append < charList[next].Count; append++)
                        {
                            newString += charList[next][append];

                            if (newString.Length <= length)
                            {
                                ChangeMin(ref dp[next, newString.Length], newString);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
            }

            var result = Inf;

            for (int i = 0; i < graph.NodeCount; i++)
            {
                ChangeMin(ref result, dp[i, length]);
            }

            if (result != Inf)
            {
                io.WriteLine(result);
            }
            else
            {
                io.WriteLine(-1);
            }
        }
Beispiel #30
0
        public override void Solve(IOManager io)
        {
            var n          = io.ReadInt();
            var tree       = new BasicGraph(n);
            var edgeIndice = new Dictionary <Edge, int>(n);

            for (int i = 0; i < n - 1; i++)
            {
                var u = io.ReadInt();
                var v = io.ReadInt();
                u--;
                v--;
                tree.AddEdge(u, v);
                tree.AddEdge(v, u);
                edgeIndice[new Edge(u, v)] = i;
            }

            var pathCount = io.ReadInt();

            var paths = new Path[pathCount];

            for (int i = 0; i < paths.Length; i++)
            {
                var u = io.ReadInt();
                var v = io.ReadInt();
                u--;
                v--;
                paths[i] = new Path(u, v);
            }

            var pathFlags = new uint[n - 1];

            for (int i = 0; i < pathCount; i++)
            {
                InitDfs(0, -1, i);
            }

            var dp = DpDfs(0, -1);

            io.WriteLine(dp[(1 << pathCount) - 1]);

            State InitDfs(int current, int parent, int pathIndex)
            {
                foreach (var next in tree[current])
                {
                    if (next == parent)
                    {
                        continue;
                    }

                    var state = InitDfs(next, current, pathIndex);

                    if (state == State.None)
                    {
                        if (next == paths[pathIndex].From)
                        {
                            pathFlags[edgeIndice[new Edge(current, next)]] |= 1u << pathIndex;
                            return(State.FirstFound);
                        }
                        else if (next == paths[pathIndex].To)
                        {
                            pathFlags[edgeIndice[new Edge(current, next)]] |= 1u << pathIndex;
                            return(State.SecondFound);
                        }
                    }
                    else if (state == State.Completed)
                    {
                        return(State.Completed);
                    }
                    else if (state == State.FirstFound)
                    {
                        pathFlags[edgeIndice[new Edge(current, next)]] |= 1u << pathIndex;

                        if (paths[pathIndex].To == current)
                        {
                            return(State.Completed);
                        }
                        else
                        {
                            return(State.FirstFound);
                        }
                    }
                    else if (state == State.SecondFound)
                    {
                        pathFlags[edgeIndice[new Edge(current, next)]] |= 1u << pathIndex;

                        if (paths[pathIndex].From == current)
                        {
                            return(State.Completed);
                        }
                        else
                        {
                            return(State.SecondFound);
                        }
                    }
                }

                return(State.None);
            }

            long[] DpDfs(int current, int parent)
            {
                var dp = new long[1 << pathCount];

                if (tree[current].Length == 1 && parent != -1)
                {
                    dp[0] = 1;
                    return(dp);
                }

                foreach (var next in tree[current])
                {
                    if (next == parent)
                    {
                        continue;
                    }

                    var currentPathFlag = pathFlags[edgeIndice[new Edge(current, next)]];
                    var childDp         = DpDfs(next, current);

                    for (var flag = BitSet.Zero; flag < 1 << pathCount; flag++)
                    {
                        // 黒くする
                        dp[flag | currentPathFlag] += childDp[flag];

                        // 白くする
                        dp[flag] += childDp[flag];
                    }
                }

                return(dp);
            }
        }