1. 程式人生 > 實用技巧 >leetcode 886. 可能的二分法(DFS,染色,種類並查集)

leetcode 886. 可能的二分法(DFS,染色,種類並查集)

題目連結

886. 可能的二分法

題意:

給定一組N人(編號為1, 2, ..., N),我們想把每個人分進任意大小的兩組。
每個人都可能不喜歡其他人,那麼他們不應該屬於同一組。
形式上,如果 dislikes[i] = [a, b],表示不允許將編號為 a 和 b 的人歸入同一組。
當可以用這種方法將所有人分進兩組時,返回 true;否則返回 false。

思路:

  1. 法一:DFS+染色
    首先初始化所有節點的顏色為0,然後給沒有染色的節點染上1,給這個節點的相鄰節點染色上-1,以此類推,判斷相鄰的兩個節點顏色相同即可

  2. 法二:種類並查集
    如果a和b不能是相同顏色,那麼我們可以合併(a,b+N),(b,a+N)為相同顏色,這樣每次判斷fa[a]和fa[b]相同即可

class Solution {
public:
    //方法二:種類並查集
    vector<int> fa;
    int findroot(int x){
        if(fa[x]==x) return x;
        return fa[x]=findroot(fa[x]);
    }
    void merge(int a,int b){
        a=findroot(a);
        b=findroot(b);
        fa[a]=b;
    }
    bool possibleBipartition(int N, vector<vector<int>>& dislikes){
        fa=vector<int>(N*2+1,0);//開兩倍空間(a,b+N),(b,a+N)來存
        //初始化fa[]陣列
        for(int i=1;i<=2*N;i++) fa[i]=i;

        for(vector<int> tmp:dislikes){
            int x=findroot(tmp[0]);
            int y=findroot(tmp[1]);
            if(x==y) return false;
            //合併(a,b+N)
            merge(tmp[0],tmp[1]+N);
            merge(tmp[1],tmp[0]+N);
        }
        return true;
    } 
    
    //方法一:
    //DFS + 染色
    // vector<int> col;//染色
    // vector<unordered_set<int>> ed;
    // bool dfs(int c,int k){
    //     col[k]=c;
    //     for(auto it=ed[k].begin();it!=ed[k].end();it++){
    //         if(col[*it]==col[k]) return false;
    //         if(!col[*it] && !dfs(-1*c,*it)) return false; 
    //     }
    //     return true;
    // }
    // bool possibleBipartition(int N, vector<vector<int>>& dislikes){
    //     col=vector<int>(N+1,0);//N個節點的顏色
    //     ed=vector<unordered_set<int>>(N+1);

    //     for(vector<int> tmp:dislikes){
    //         ed[tmp[0]].insert(tmp[1]);
    //         ed[tmp[1]].insert(tmp[0]);//創立鄰接連結串列
    //     }

    //     for(int i=1;i<=N;i++){
    //         if(!col[i] && !dfs(1,i)) return false;
    //     }

    //     return true;
    // }


    // static bool cmp(vector<int> a,vector<int> b){
    //     if(a[0]==b[0]) return a[1]<b[1];
    //     return a[0]<b[0];
    // }
    // bool possibleBipartition(int N, vector<vector<int>>& dislikes) {
    //     vector<vector<int>> ans;
    //     for(vector<int> tmp:dislikes){
    //         if(tmp[0]>tmp[1]) swap(tmp[1],tmp[0]);
    //         ans.push_back(tmp);
    //     }
        
    //     sort(ans.begin(),ans.end());
    //     set<int> s1,s2;
    //     for(vector<int> tmp:ans){
    //         if(s1.count(tmp[1]) || s2.count(tmp[0])) return false;
    //         s1.insert(tmp[0]);
    //         s2.insert(tmp[1]);
    //     }
    //     return true;
    // }
};