1. 程式人生 > >(LeetCode 886)可能的二分法 [01著色問題,dfs模擬]

(LeetCode 886)可能的二分法 [01著色問題,dfs模擬]

886. 可能的二分法
給定一組 N 人(編號為 1, 2, …, N), 我們想把每個人分進任意大小的兩組。

每個人都可能不喜歡其他人,那麼他們不應該屬於同一組。

形式上,如果 dislikes[i] = [a, b],表示不允許將編號為 a 和 b 的人歸入同一組。

當可以用這種方法將每個人分進兩組時,返回 true;否則返回 false。

示例 1:

輸入:N = 4, dislikes = [[1,2],[1,3],[2,4]]
輸出:true
解釋:group1 [1,4], group2 [2,3]
示例 2:

輸入:N = 3, dislikes = [[1,2],[1,3],[2,3]]
輸出:false
示例 3:

輸入:N = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]]
輸出:false

提示:

1 <= N <= 2000
0 <= dislikes.length <= 10000
1 <= dislikes[i][j] <= N
dislikes[i][0] < dislikes[i][1]
對於 dislikes[i] == dislikes[j] 不存在 i != j

分析:
本題就是直接使用DFS(或BFS)進行模擬。將所有人分為兩組,就是給所有人在0,1兩種顏色上著色,使其不衝突。

首先所有的節點都沒有著色,標記為-1。
對任意的聯通分量,第一個節點我們可以隨意著色,(著色為1),然後進行DFS對其他相鄰的節點進行著色。
若該節點沒有被著色,則將其著色為另外一種顏色,並遞迴對其相鄰節點進行著色。
若該節點已經著色,則只需判斷這兩個相鄰的節點的顏色是否相同,相同則存在衝突。

AC程式碼:

class Solution {
public:
    int c[2019];
    vector<int> e[2019];
    
    int dfs(int id,int color)
    {
        c[id] = color;
        int ans = 1;
        for(int i=0;i<e[id].size();i++)
        {
            if(c[e[id][i]] == -1) ans &= dfs(e[id][i],color^1);
            else if(c[e[id][i]] == color)
            {
                ans = 0;
                break;
            }
        }
        return ans;
    }
    
    bool possibleBipartition(int N, vector<vector<int>>& dislikes) {
        if(N<=2) return true;
        memset(c,-1,sizeof(c));
        int m = dislikes.size();
        for(int i=0;i<m;i++)
        {
            e[dislikes[i][0]].push_back(dislikes[i][1]);
            e[dislikes[i][1]].push_back(dislikes[i][0]);
        }
        int ans = 1;
        for(int i=1;i<=N;i++)
        {
            if(c[i] == -1)
                ans &= dfs(i,1);
        }
        return ans;
    }
};