<p>There is an <strong>undirected</strong> graph consisting of <code>n</code> nodes numbered from <code>1</code> to <code>n</code>. You are given the integer <code>n</code> and a <strong>2D</strong> array <code>edges</code> where <code>edges[i] = [a<sub>i</sub>, b<sub>i</sub>]</code> indicates that there is an edge between nodes <code>a<sub>i</sub></code> and <code>b<sub>i</sub></code>. The graph can be disconnected.</p>

<p>You can add <strong>at most</strong> two additional edges (possibly none) to this graph so that there are no repeated edges and no self-loops.</p>

<p>Return <code>true</code><em> if it is possible to make the degree of each node in the graph even, otherwise return </em><code>false</code><em>.</em></p>

<p>The degree of a node is the number of edges connected to it.</p>

<p>&nbsp;</p>
<p><strong>Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2022/10/26/agraphdrawio.png" style="width: 500px; height: 190px;" />
<pre>
<strong>Input:</strong> n = 5, edges = [[1,2],[2,3],[3,4],[4,2],[1,4],[2,5]]
<strong>Output:</strong> true
<strong>Explanation:</strong> The above diagram shows a valid way of adding an edge.
Every node in the resulting graph is connected to an even number of edges.
</pre>

<p><strong>Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2022/10/26/aagraphdrawio.png" style="width: 400px; height: 120px;" />
<pre>
<strong>Input:</strong> n = 4, edges = [[1,2],[3,4]]
<strong>Output:</strong> true
<strong>Explanation:</strong> The above diagram shows a valid way of adding two edges.</pre>

<p><strong>Example 3:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2022/10/26/aaagraphdrawio.png" style="width: 150px; height: 158px;" />
<pre>
<strong>Input:</strong> n = 4, edges = [[1,2],[1,3],[1,4]]
<strong>Output:</strong> false
<strong>Explanation:</strong> It is not possible to obtain a valid graph with adding at most 2 edges.</pre>

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

<ul>
	<li><code>3 &lt;= n &lt;= 10<sup>5</sup></code></li>
	<li><code>2 &lt;= edges.length &lt;= 10<sup>5</sup></code></li>
	<li><code>edges[i].length == 2</code></li>
	<li><code>1 &lt;= a<sub>i</sub>, b<sub>i</sub> &lt;= n</code></li>
	<li><code>a<sub>i</sub> != b<sub>i</sub></code></li>
	<li>There are no repeated edges.</li>
</ul>

class Solution:
    def isPossible(self, n: int, edges: List[List[int]]) -> bool:
        # we need to identify nodes with an odd degree 
        # every new connection increases a degree of two nodes by one
        # so we need to fix odd nodes and not to break even ones
        # so we connect only odd nodes to each other
        # how many can we connect? 0 is great, 2 nodes with one,
        # and 4 nodes with 2 new edges
        # important to check that they don't have this connection already
        # bcs if desired connection already exists, it's gameover
        graph = {i: [] for i in range(1, n + 1)}
        nodes_even_status = {i: True for i in range(1, n + 1)}
        for start, end in edges:  # O(E)
            graph[start].append(end)
            graph[end].append(start)
            nodes_even_status[start] = not nodes_even_status[start]
            nodes_even_status[end] = not nodes_even_status[end]

        odd_ids = [k for k, v in nodes_even_status.items() if not v]
        if not odd_ids:
            return True

        if len(odd_ids) == 2:
            first, second = odd_ids
            can_build_direct_connection = second not in graph[first]
            node_not_connected_with_both = False
            for k, v in graph.items():
                if (k not in [first, second]) and (first not in v) and (second not in v):
                    node_not_connected_with_both = True
            return can_build_direct_connection or node_not_connected_with_both
        elif len(odd_ids) == 4:
            first, second, third, fourth = odd_ids
            # 1-2 and 3-4
            # 1-3 and 2-4
            # 1-4 and 2-3
            return (
                       ((first not in graph[second]) and (third not in graph[fourth]))
                    or ((first not in graph[third]) and (second not in graph[fourth]))
                    or ((first not in graph[fourth]) and (second not in graph[third]))
                    )

        return False
63378