↓快轉到主要內容
  1. LeetCode/

LeetCode 3910: Count Connected Subgraphs with Even Node Sum

·1 分鐘· ·
LeetCode Hard Bit-Manipulation Enumeration Graph Union-Find
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-04-26

  • 提交紀錄:Accepted → Accepted(整理一次)

解題思路
#

數有幾個非空的節點子集合,滿足:

  1. 只保留子集合裡的節點和它們之間的邊(誘導子圖),而且這個子圖是連通的。
  2. 子集合裡節點值的和是偶數。

節點數很小,可以用位元遮罩枚舉全部 2^n - 1 個子集合,每個子集合:

  1. 先檢查和是不是偶數,比較便宜,不符合就跳過。
  2. 再檢查誘導子圖是不是連通:從子集合裡任一點開始 BFS,只走子集合內的邊,看能不能走到所有點。

我的解法
#

原本是用 Union-Find 檢查連通:只合併兩端都在子集合裡的邊,最後看子集合的點是不是都在同一個根底下。這裡改用 BFS,邏輯一樣,但不用每個子集合都重建 parent 陣列:

class Solution:
    def evenSumSubgraphs(self, nums: List[int], edges: List[List[int]]) -> int:
        n = len(nums)
        adj = [0] * n                              # 鄰居也用位元遮罩表示
        for u, v in edges:
            adj[u] |= 1 << v
            adj[v] |= 1 << u

        count = 0
        for mask in range(1, 1 << n):
            if sum(nums[i] for i in range(n) if mask >> i & 1) % 2:
                continue
            start = (mask & -mask).bit_length() - 1     # 最低位的點
            seen = 1 << start
            frontier = seen
            while frontier:
                nxt = 0
                for i in range(n):
                    if frontier >> i & 1:
                        nxt |= adj[i]
                nxt &= mask & ~seen                # 只走子集合內、還沒拜訪的點
                seen |= nxt
                frontier = nxt
            if seen == mask:
                count += 1
        return count

鄰居用位元遮罩存,「只走子集合內的點」就是一個 & mask。

LeetCode 的題目敘述裡要求在函式中途建立一個指定名稱的變數來存輸入,原本交的版本有照做;它不影響演算法,這裡省略。

複雜度
#

時間 O(2^n · n^2):每個子集合 BFS 最多 n 層,每層掃 n 個點。空間 O(n)。

要特別避免的錯誤
#

  • 檢查連通時用了子集合外的邊或點:只能走「兩端都在子集合裡」的邊。
  • 空集合也算進去:遮罩要從 1 開始。
  • 先檢查連通再檢查和:和的檢查比較便宜,先做就能提早跳過不符合的子集合。

面試口說整理
#

節點數很小,所以我用位元遮罩枚舉所有非空子集合。每個子集合先檢查節點值的和是不是偶數,不是就跳過;是的話,從子集合裡任一點做 BFS,只走子集合內的點,最後走到的點等於整個子集合就是連通的。鄰居存成位元遮罩,限制在子集合內只要一個 & mask。時間 O(2^n · n^2)。

相關文章

LeetCode 3827: Count Monobit Integers
·1 分鐘
LeetCode Easy Bit-Manipulation Enumeration
LeetCode 3827 解題筆記:每一位都一樣的數只有 0 和 2^k - 1;個數就是 (n + 1).bit_length()
LeetCode 2122: Recover the Original Array
·2 分鐘
LeetCode Hard Two-Pointers Sorting Hash-Table Enumeration Array
LeetCode 2122 解題筆記:最小的數一定在 lower,枚舉它的配對決定 k;排序後用兩個指針把每個最小的未配對數配給 +2k 的數
LeetCode 1782: Count Pairs Of Nodes
·2 分鐘
LeetCode Hard Two-Pointers Graph Sorting Hash-Table Counting
LeetCode 1782 解題筆記:先用排序後的度數 + 對撞指針數 deg[a] + deg[b] > q 的配對,再對有共用邊的配對修正多算的部分
LeetCode 3493: Properties Graph
·1 分鐘
LeetCode Medium Graph Dfs Union-Find Hash-Map
LeetCode 3493 解題筆記:先把每列轉成 set,兩兩比較交集大小建邊,再數連通塊
LeetCode 269: Alien Dictionary
·2 分鐘
LeetCode Hard Graph Topological-Sort
LeetCode 269 解題筆記,依照原始 learning note 重新整理
LeetCode 778: Swim in Rising Water
·2 分鐘
LeetCode Hard Graph Dijkstra Binary-Search
LeetCode 778 解題筆記,依照原始 learning note 重新整理