二分图: 如果能将一个无向图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,那么就将这个图称为二分图。
判断二分图: 对于一个顶点大于2的无向图,其所有回路的顶点个数必须为偶数。
算法思路: 染色法,记忆化递归。深度优先遍历(或广度优先遍历)所有顶点并保存前一个顶点的状态pre,对于当前顶点cur,如果cur已经染色且与pre的颜色相同则说明这不是无向图。如果cur未被染色,pre为无色则将cur染成红色否则将cur染成与其不同的颜色。遍历正常结束时说明是无向图。
代码:
bool invaild = 0;
vector<int> state;//储存状态,0为无色,1为红色,2为蓝色
void DFS(vector<vector<int>>& graph, int i, int pre) //graph为邻接表
{
if (state[i] != 0)//已被染色就可以退出
{
if (state[i] == pre) invaild = 1; //此时说明无效
return;
}
//染色
if (pre == 0 || pre == 2) state[i] = 1;
else if (pre == 1) state[i] = 2;
for (int j = 0; j < graph[i].size(); ++j)
{
if (!invaild)
{
DFS(graph, graph[i][j], state[i]);
}
}
return;
}
bool isBipartite(vector<vector<int>>& graph)
{
state.resize(graph.size());//初始化是0
for (int i = 0; i < graph.size(); ++i)
{
if (!invaild)
{
DFS(graph, i, 0);
}
}
return !invaild;
}