Add Edges to Make Degrees of All Nodes Even

Add Edges to Make Degrees of All Nodes Even

There is an undirected graph consisting of $n$ nodes numbered from $1$ to $n$. You are given the integer $n$ and a 2D array edges where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi . The graph can be disconnected.

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

Return true if it is possible to make the degree of each node in the graph even, otherwise return false.

The degree of a node is the number of edges connected to it.

Example 1:

Input: n = 5, edges = [[1,2],[2,3],[3,4],[4,2],[1,4],[2,5]]
Output: true
Explanation: 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.

Example 2:

Input: n = 4, edges = [[1,2],[3,4]]
Output: true
Explanation: The above diagram shows a valid way of adding two edges.

Example 3:

Input: n = 4, edges = [[1,2],[1,3],[1,4]]
Output: false
Explanation: It is not possible to obtain a valid graph with adding at most 2 edges.

Constraints:

$2 \leq \text{edges.length} \leq {10}^{5}$
$\text{edges}[i]\text{.length} \mathrm{==} 2$
$1 \leq a_i, b_i \leq n$
$a_i \ne b_i$
There are no repeated edges.

 

解题思路

  这题就是分类讨论。

  首先容易发现加一条边最多可以将两个度数为奇数的结点变成偶数,又因为最多可以加两条边,因此如果图中度数为奇数的结点个数超过$4$个那么就无解。

  然后如果要加一条边,那么这条边对应的两个结点的度数有$3$种情况:两个都是奇数、两个都是偶数、一个是奇数一个是偶数。

  • 如果给两个度数为奇数的结点连一条边,这两个结点的度数都变成偶数,那么图中度数为奇数的结点的个数就会减少$2$。
  • 如果给两个度数为偶数的结点连一条边,这两个结点的度数都变成奇数,那么图中度数为奇数的结点的个数就会增加$2$。
  • 如果给两个度数奇偶性不同的结点连一条边,这两个结点的度数依然是一个奇数一个偶数,那么图中度数为奇数的结点的个数不变。

  因此可以发现无论怎么连边,图中度数为奇数的结点的个数的奇偶性不会变。又因为最后要保证图中度数为奇数的结点个数为$0$,因此如果图中度数为奇数的结点个数为奇数个,那么无解。事实上度数为奇数的结点个数是奇数这种情况是不可能会发生的。这是因为如果有奇数个度数为奇数的结点,那么把所有结点的度数进行累加后总度数就为奇数,而每条边都与两个结点相连,意味着每条边的度数贡献为$2$,因此总的度数应该为偶数,这就矛盾了。

  因此度数为奇数的结点个数可以分成三种情况:$0$、$2$、$4$。

  对于$0$的情况,直接返回$\text{true}$。

  对于$2$的情况,分连一条边和连两条边的情况。如果要连一条边,那么就应该给这两个结点间连一条边,因为不能有重边,因此只有当这条边不存在才可以连。否则考虑连两条边,在其余的点中找一个点(这个点的度数必然是偶数),然后这个点分别与两个度数为奇数的点连一条边(一样要保证不能有重边)。

  对于$4$的情况,此时必然要把这$4$个度数为奇数的点中分成两组,组内两两连一条边。可以通过枚举全排列或者组合来进行分组,只要存在一种分组情况是可以连边的(无重边),那么就有解。

  AC代码如下:

 1 class Solution {
 2 public:
 3     bool isPossible(int n, vector<vector<int>>& edges) {
 4         vector<int> deg(n + 1);
 5         set<pair<int, int>> st; // 哈希表,统计某条边是否出现过
 6         for (auto &p : edges) {
 7             deg[p[0]]++, deg[p[1]]++;
 8             st.insert({p[0], p[1]}), st.insert({p[1], p[0]});
 9         }
10         vector<int> p;
11         for (int i = 1; i <= n; i++) {
12             if (deg[i] & 1) p.push_back(i); // 找到度数为奇数的点
13         }
14         if (p.size() == 0) {
15             return true;
16         }
17         else if (p.size() == 2) {
18             if (!st.count({p[0], p[1]})) return true;   // 这两个点之间可以连一条边
19             for (int i = 1; i <= n; i++) {  // 找到这两个点之外的点,分别与这两个点连一条边
20                 if (i != p[0] && i != p[1] && !st.count({p[0], i}) && !st.count({p[1], i})) return true;
21             }
22         }
23         else if (p.size() == 4) {
24             do {
25                 if (!st.count({p[0], p[1]}) && !st.count({p[2], p[3]})) return true;    // 组内两点都可以连一条边
26             } while (next_permutation(p.begin(), p.end()));
27         }
28         return false;
29     }
30 };

 

参考资料

  力扣第324场周赛:https://www.bilibili.com/video/BV1wD4y1h7Vz/

posted @ 2022-12-18 17:31  onlyblues  阅读(12)  评论(0编辑  收藏  举报
Web Analytics