Modern C# code solution, MinHeap + BFS
\npublic class Solution {\n    public int CutOffTree(IList<IList<int>> forest) {\n        \n        // The main idea is that we will put all the trees in minHea
```\npublic class Solution {\n    public int CutOffTree(IList<IList<int>> forest) {\n        \n        // The main idea is that we will put all the trees in minHeap in order to\n        // cut them from lower height to higher.\n        // Then, to find out distance between two adjacent trees we\'ll use BFS\n        const int BLOCK = 0;\n        \n        var directions = new (int dR, int dC)[] { (-1, 0), (0, 1), (1, 0), (0, -1) };\n        \n        int rows = forest.Count;\n        int columns = forest[0].Count;\n        \n        PriorityQueue<(int row, int column), int> minHeap = new();\n        \n        for (int row = 0; row < rows; row++)\n            for (int column = 0; column < columns; column++)\n            {\n                int height = forest[row][column];\n                \n                if (height > 1) minHeap.Enqueue((row, column), height);\n            }\n              \n        int totalSteps = 0;\n        (int row, int column) source = (0, 0);\n        \n        while (minHeap.TryDequeue(out var target, out _))\n        {\n            int stepsTaken = minSteps(source.row, source.column, target.row, target.column);\n            \n            if (stepsTaken == -1) return -1;\n            \n            totalSteps += stepsTaken;\n            \n            source = target;\n        }\n        \n        return totalSteps;\n        \n        int minSteps(int sourceRow, int sourceColumn, int targetRow, int targetColumn)\n        {\n            HashSet<(int, int)> visited = new();\n            Queue<(int, int)> queue = new();\n            \n            queue.Enqueue((sourceRow, sourceColumn));\n            \n            int steps = 0;\n            \n            while (queue.Count > 0)\n            {\n                int layerLength = queue.Count;\n                \n                for (int i = 0; i < layerLength; i++)\n                {\n                    (int row, int column) = queue.Dequeue();\n                \n                    if (row == targetRow && column == targetColumn) return steps;\n                    \n                    foreach (var direction in directions)\n                    {\n                        int nextRow = row + direction.dR;\n                        int nextColumn = column + direction.dC;\n                        \n                        if (nextRow < 0 || nextRow >= rows || nextColumn < 0 || \n                            nextColumn >= columns || forest[nextRow][nextColumn] == BLOCK) continue;\n                        \n                        if (visited.Contains((nextRow, nextColumn))) continue;\n                        \n                        visited.Add((nextRow, nextColumn));\n                        queue.Enqueue((nextRow, nextColumn));\n                    }\n                }\n                \n                steps++;\n            }\n            \n            return -1;            \n        }        \n    }\n}\n```
[]