<p>There is an <code>m x n</code> rectangular island that borders both the <strong>Pacific Ocean</strong> and <strong>Atlantic Ocean</strong>. The <strong>Pacific Ocean</strong> touches the island&#39;s left and top edges, and the <strong>Atlantic Ocean</strong> touches the island&#39;s right and bottom edges.</p>

<p>The island is partitioned into a grid of square cells. You are given an <code>m x n</code> integer matrix <code>heights</code> where <code>heights[r][c]</code> represents the <strong>height above sea level</strong> of the cell at coordinate <code>(r, c)</code>.</p>

<p>The island receives a lot of rain, and the rain water can flow to neighboring cells directly north, south, east, and west if the neighboring cell&#39;s height is <strong>less than or equal to</strong> the current cell&#39;s height. Water can flow from any cell adjacent to an ocean into the ocean.</p>

<p>Return <em>a <strong>2D list</strong> of grid coordinates </em><code>result</code><em> where </em><code>result[i] = [r<sub>i</sub>, c<sub>i</sub>]</code><em> denotes that rain water can flow from cell </em><code>(r<sub>i</sub>, c<sub>i</sub>)</code><em> to <strong>both</strong> the Pacific and Atlantic oceans</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/06/08/waterflow-grid.jpg" style="width: 400px; height: 400px;" />
<pre>
<strong>Input:</strong> heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
<strong>Output:</strong> [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]
<strong>Explanation:</strong> The following cells can flow to the Pacific and Atlantic oceans, as shown below:
[0,4]: [0,4] -&gt; Pacific Ocean 
&nbsp;      [0,4] -&gt; Atlantic Ocean
[1,3]: [1,3] -&gt; [0,3] -&gt; Pacific Ocean 
&nbsp;      [1,3] -&gt; [1,4] -&gt; Atlantic Ocean
[1,4]: [1,4] -&gt; [1,3] -&gt; [0,3] -&gt; Pacific Ocean 
&nbsp;      [1,4] -&gt; Atlantic Ocean
[2,2]: [2,2] -&gt; [1,2] -&gt; [0,2] -&gt; Pacific Ocean 
&nbsp;      [2,2] -&gt; [2,3] -&gt; [2,4] -&gt; Atlantic Ocean
[3,0]: [3,0] -&gt; Pacific Ocean 
&nbsp;      [3,0] -&gt; [4,0] -&gt; Atlantic Ocean
[3,1]: [3,1] -&gt; [3,0] -&gt; Pacific Ocean 
&nbsp;      [3,1] -&gt; [4,1] -&gt; Atlantic Ocean
[4,0]: [4,0] -&gt; Pacific Ocean 
       [4,0] -&gt; Atlantic Ocean
Note that there are other possible paths for these cells to flow to the Pacific and Atlantic oceans.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> heights = [[1]]
<strong>Output:</strong> [[0,0]]
<strong>Explanation:</strong> The water can flow from the only cell to the Pacific and Atlantic oceans.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>m == heights.length</code></li>
	<li><code>n == heights[r].length</code></li>
	<li><code>1 &lt;= m, n &lt;= 200</code></li>
	<li><code>0 &lt;= heights[r][c] &lt;= 10<sup>5</sup></code></li>
</ul>

class Solution {
public:
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
        int m = heights.size();
        int n = heights[0].size();
        std::vector<std::vector<int>> result;
        std::vector<std::vector<std::pair<bool,bool>>> valid;
        std::vector<std::vector<bool>> seen;
        std::stack<std::pair<int,int>> visited;
        for (int i = 0; i < m; i++)
        {
            std::vector<std::pair<bool,bool>> temp;
            valid.push_back(temp);
            std::vector<bool> temp2;
            seen.push_back(temp2);
            for (int j = 0; j < n; j++)
            {
                valid[i].push_back(std::make_pair(false, false));
                seen[i].push_back(false);
            };
        };
        for (int k = 0; k < m; k++)
        {
            visited.push(std::make_pair(k, 0));
            while(!visited.empty())
            {
                std::pair<int,int> curr = visited.top();
                visited.pop();
                int i = curr.first;
                int j = curr.second;
                std::cout << i << " " << j << "\n";
                if (valid[i][j].first == false)
                {
                    valid[i][j].first = true;
                    if (valid[i][j].second == true)
                    {
                        result.push_back({i,j});
                    };
                };
                
                seen[i][j] = true;
                int h = heights[i][j];
                if (i > 0 && !seen[i - 1][j] && h <= heights[i - 1][j])
                {
                    visited.push(std::make_pair(i - 1, j));
                };
                if (i < m - 1 && !seen[i + 1][j] && h <= heights[i + 1][j])
                {
                    visited.push(std::make_pair(i + 1, j));
                };

                if (j > 0 && !seen[i][j - 1] && h <= heights[i][j - 1])
                {
                    visited.push(std::make_pair(i, j - 1));
                };
                if (j < n - 1 && !seen[i][j + 1] && h <= heights[i][j + 1])
                {
                    visited.push(std::make_pair(i, j + 1));
                };
            };

            for (int i = 0; i < m; ++i)
            {
                for (int j = 0; j < n; ++j)
                {
                    seen[i][j] = false;
                };
            };

            visited.push(std::make_pair(k, n - 1));
            while(!visited.empty())
            {
                std::pair<int,int> curr = visited.top();
                visited.pop();
                int i = curr.first;
                int j = curr.second;
                if (valid[i][j].second == false)
                {
                    valid[i][j].second = true;
                    if (valid[i][j].first == true)
                    {
                        result.push_back({i,j});
                    };
                };
                
                seen[i][j] = true;
                int h = heights[i][j];
                if (i > 0 && !seen[i - 1][j] && h <= heights[i - 1][j])
                {
                    visited.push(std::make_pair(i - 1, j));
                };
                if (i < m - 1 && !seen[i + 1][j] && h <= heights[i + 1][j])
                {
                    visited.push(std::make_pair(i + 1, j));
                };

                if (j > 0 && !seen[i][j - 1] && h <= heights[i][j - 1])
                {
                    visited.push(std::make_pair(i, j - 1));
                };
                if (j < n - 1 && !seen[i][j + 1] && h <= heights[i][j + 1])
                {
                    visited.push(std::make_pair(i, j + 1));
                };
            };

            for (int i = 0; i < m; ++i)
            {
                for (int j = 0; j < n; ++j)
                {
                    seen[i][j] = false;
                };
            };
        }

        for (int k = 0; k < n; k++)
        {
            visited.push(std::make_pair(0, k));
            while(!visited.empty())
            {
                std::pair<int,int> curr = visited.top();
                visited.pop();
                int i = curr.first;
                int j = curr.second;
                if (valid[i][j].first == false)
                {
                    valid[i][j].first = true;
                    if (valid[i][j].second == true)
                    {
                        result.push_back({i,j});
                    };
                };
                
                seen[i][j] = true;
                int h = heights[i][j];
                if (i > 0 && !seen[i - 1][j] && h <= heights[i - 1][j])
                {
                    visited.push(std::make_pair(i - 1, j));
                };
                if (i < m - 1 && !seen[i + 1][j] && h <= heights[i + 1][j])
                {
                    visited.push(std::make_pair(i + 1, j));
                };

                if (j > 0 && !seen[i][j - 1] && h <= heights[i][j - 1])
                {
                    visited.push(std::make_pair(i, j - 1));
                };
                if (j < n - 1 && !seen[i][j + 1] && h <= heights[i][j + 1])
                {
                    visited.push(std::make_pair(i, j + 1));
                };
            };

            for (int i = 0; i < m; ++i)
            {
                for (int j = 0; j < n; ++j)
                {
                    seen[i][j] = false;
                };
            };

            visited.push(std::make_pair(m - 1, k));
            while(!visited.empty())
            {
                std::pair<int,int> curr = visited.top();
                visited.pop();
                int i = curr.first;
                int j = curr.second;
                if (valid[i][j].second == false)
                {
                    valid[i][j].second = true;
                    if (valid[i][j].first == true)
                    {
                        result.push_back({i,j});
                    };
                };
                seen[i][j] = true;
                int h = heights[i][j];
                if (i > 0 && !seen[i - 1][j] && h <= heights[i - 1][j])
                {
                    visited.push(std::make_pair(i - 1, j));
                };
                if (i < m - 1 && !seen[i + 1][j] && h <= heights[i + 1][j])
                {
                    visited.push(std::make_pair(i + 1, j));
                };

                if (j > 0 && !seen[i][j - 1] && h <= heights[i][j - 1])
                {
                    visited.push(std::make_pair(i, j - 1));
                };
                if (j < n - 1 && !seen[i][j + 1] && h <= heights[i][j + 1])
                {
                    visited.push(std::make_pair(i, j + 1));
                };
            };
            
            for (int i = 0; i < m; ++i)
            {
                for (int j = 0; j < n; ++j)
                {
                    seen[i][j] = false;
                };
            };
        };
        return result;
    }
};
31600