给定一个无向图graph,当这个图为二分图时返回true。
如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。
graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自环和平行边: graph[i] 中不存在i,并且graph[i]中没有重复的值。
观看二分图的性质,显然有:二分图把图的定点分成两个子集,每个子集之内的元素要求不能有连通到本集合内部的边.
设最终的二分点集是 G 1 , G 2 G_1,G_2 G1,G2
所以边是我们区分点集的手段,对于一个节点i,假设i在点集 G 1 G_1 G1内,那么和他有边的节点集合 S i S_i Si是 G 2 G_2 G2的一个子集.
我们依次遍历节点和它的边,检查每个边的另一个端点的集合,假如和i节点的集合一致(root一致),那么就不能二分( G 1 ∣ ∣ G 2 G_1||G_2 G1∣∣G2内部出现了边)
每条边在遍历中会出现2次,因此不用担心出现遗漏的情况
另外,如果统计并查集中最终集合的数量,可能是会大于2的.但是这种多集合的情况也满足二分图的性质(可以任意合并2个集合直到剩余两个集合,这两个集合也满足二分图的性质)
20分钟
#include
#include
using namespace std;
class Solution
{
public:
vector<int> parent;
int findRoot(int x)
{
int oriX = x;
while (parent[x] != x)
{
x = parent[x];
}
while (parent[oriX] != x)
{
int temp = parent[oriX];
parent[oriX] = x;
oriX = temp;
}
return x;
}
void unionNode(int sun, int father)
{
parent[sun] = father;
return;
}
bool isBipartite(vector<vector<int>> &graph)
{
int size = graph.size();
//initalize
parent.resize(size);
for (int i = 0; i < size; i++)
{
parent[i] = i;
}
//
for (int i = 0; i < size; i++)
{
int roota = findRoot(i);
int edgeSize = graph[i].size();
if (edgeSize > 0)
{
int rootb = findRoot(graph[i][0]);
if (rootb == roota)
{
return false;
}
for (int j = 1; j < edgeSize; j++)
{
int rootc = findRoot(graph[i][j]);
if (findRoot(graph[i][j]) == roota)
{
return false;
}
unionNode(rootc, rootb);
}
}
}
return true;
}
};
int main(int argc, char const *argv[])
{
return 0;
}
看在我写了这么多注释的份上可以给我点个赞嘛,求求惹=]砰砰砰,给我加点写下去的油呀
@.@
也欢迎关注我的CSDN账号呀=]
**开心code每一天**