###### tags: `Leetcode` `medium` `graph` `bfs` `union find` `python` `c++`
# 886. Possible Bipartition
## [題目連結:] https://leetcode.com/problems/possible-bipartition/description/
## 題目:
We want to split a group of ```n``` people (labeled from ```1``` to ```n```) into two groups of **any size**. Each person may dislike some other people, and they should not go into the same group.
Given the integer n and the array ```dislikes``` where ```dislikes[i] = [ai, bi]``` indicates that the person labeled ```ai``` does not like the person labeled ```bi```, return ```true``` if it is possible to split everyone into two groups in this way.
**Example 1:**
```
Input: n = 4, dislikes = [[1,2],[1,3],[2,4]]
Output: true
Explanation: group1 [1,4] and group2 [2,3].
```
**Example 2:**
```
Input: n = 3, dislikes = [[1,2],[1,3],[2,3]]
Output: false
```
**Example 3:**
```
Input: n = 5, dislikes = [[1,2],[2,3],[3,4],[4,5],[1,5]]
Output: false
```
## 解題想法:
* 此題為二分圖: 相鄰的兩點不能為同個群組
* 使用BFS拜訪:
* 進行顏色判別:
* 0: Unknown
* 1: visited First Group
* 2: visited Second Group
* 流程:
* Step1:
* 建立雙向邊 graph
* visited=[0]* (n+1)
* visited[i]對應i person
* Step2:
* for i in range(1,n+1) #因為題目說1~n,並非從0開始
* 若visited[i]=0: 才進行後續Step3判斷
* Step3:
* 將當前visited[i]=1
* que=[i] #紀錄此位置
* Step4:
* while que:
* 當前que中的node=curPos
* 判斷curPos的鄰居是否進行著色:
* 若visited[neighber]==0:
* 填入與visited[curPos]的顏色
* **que.append(neighber)**
* 否則若與visited[curPos]相同:
* return False
## Python:
``` python=
from collections import defaultdict
class Solution(object):
def possibleBipartition(self, n, dislikes):
"""
:type n: int
:type dislikes: List[List[int]]
:rtype: bool
"""
#對每點進行渲染:
#0: UnKnown 1、2: visited
#若相鄰的衝突 則為false
graph=defaultdict(list)
for u,v in dislikes:
graph[u].append(v)
graph[v].append(u)
visited=[0]*(n+1) #v[i]對應i person
for i in range(1,n+1):
if visited[i]==0: #尚未拜訪
visited[i]=1 #設為1
que=[i]
while que:
curPos=que.pop(0)
for neighber in graph[curPos]:
if visited[neighber]==0: #鄰居填入不同顏色
visited[neighber]=2 if visited[curPos]==1 else 1
que.append(neighber)
elif visited[neighber]==visited[curPos]:
return False
return True
```
## C++:
``` cpp=
class Solution {
public:
bool possibleBipartition(int n, vector<vector<int>>& dislikes) {
unordered_map<int, vector<int>> graph;
vector<int> visited(n+1,0);
//connect the graph
for (auto item: dislikes){
graph[item[0]].push_back(item[1]);
graph[item[1]].push_back(item[0]);
}
queue<int> que;
//check neighber
for (int i=1; i<n+1; i++){
if (visited[i]==0){
visited[i]=1;
que.push(i);
while (!que.empty()){
int curPos=que.front(); que.pop();
for (auto neighber: graph[curPos]){
if (visited[neighber]==0){ //paint on different color
visited[neighber]= (visited[curPos]==1)? 2:1;
que.push(neighber);
}
else if (visited[neighber]==visited[curPos]){
return false;
}
}
}
}
}
return true;
}
};
```