<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:
    degrees = {u: 0 for u in range(1, n+1)}
    g = defaultdict(set)
    
    for u1, u2 in edges:
      degrees[u1] += 1
      degrees[u2] += 1
      g[u1].add(u2)
      g[u2].add(u1)

    odds = []
    for i in range(1, n+1):
      if degrees[i] & 1:
        odds.append(i)

    # an edge changes the degrees of two nodes,
    # so if we have 1 or 3 odd nodes, it's impossible
    # to get rid of all the odds.
    if len(odds) not in {0, 2, 4}:
      return False
    
    if len(odds) == 0:
      return True
    
    if len(odds) == 2:
      u1, u2 = odds
      # if edge already exists, there needs to be an even
      # node that isn't yet connected to either odd one
      if u2 in g[u1]:
        for node in range(1, n+1):
          if node != u1 and node != u2:
            if u1 not in g[node] and u2 not in g[node]:
              return True
        return False

      # if edge doesn't already exist, just connect them
      else:
        return True

    if len(odds) == 4:
      # we need to use each of our edges to
      # make two odd nodes even.

      # just need to have two available edges,
      # one between a/b and one between c/d

      u1, u2, u3, u4 = odds
      avail_for_u1 = {u2, u3, u4} - g[u1]

      # if u1 is already connected to
      # the other three, then impossible
      if not avail_for_u1:
        return False

      # if not, for each node u1 can connect to,
      # check if the other two can connect.
      # if any of those combinations work, return True.
      is_valid = False
      for node in avail_for_u1:
        if node == u2:
          is_valid = is_valid or u4 not in g[u3]
        if node == u3:
          is_valid = is_valid or u4 not in g[u2]
        if node == u4:
          is_valid = is_valid or u3 not in g[u2] 
      return is_valid

63696