判断二分图(Java)
题目描述
给定一个无向图graph,当这个图为二分图时返回true。
如果我们能将一个图的节点集合分割成两个独立的子集A和B,并使图中的每一条边的两个节点一个来自A集合,一个来自B集合,我们就将这个图称为二分图。
graph将会以邻接表方式给出,graph[i]表示图中与节点i相连的所有节点。每个节点都是一个在0到graph.length-1之间的整数。这图中没有自环和平行边:
graph[i] 中不存在i,并且graph[i]中没有重复的值。
示例
二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。
判断二分图有一个十分经典的方法:染色法。
随意选择一个顶点,将其染色,然后其所有相邻的顶点染上另一种颜色。接着对相邻顶点进行同样的操作,即将最开始选择的顶点的相邻顶点的相邻顶点染成和最开始选择顶点一样的颜色,看着有些绕,继续往下看,示例解释中可能要清晰些。
若是染色途中发现邻居顶点已经被染色,而且和当前结点颜色一样,那么证明这不是一个二分图,同时这也就保证了染色完毕后相邻顶点不会是同样的颜色。
如示例1中,先选取顶点0,染上红色,那么其相邻顶点1,3就染成黑色。接着将和1,3相邻的顶点2染成红色。这样,集合就分为了红色的{0,2},黑色的{1,3}.满足条件,返回true。
染色完毕后,颜色相同的顶点为一个集合。由上面的分析可知道,总共两种颜色,同种颜色的集合中不会出现相邻顶点。
深度优先遍历
private class Solution {
private static final int UNCOLORED = 0;//表示未染色
private static final int RED = 1;
private static final int BLACK = 2;
private int[] color;//表示每个节点的染色情况
//判断是否是二分图。相邻结点不是同一颜色即可
public boolean isBipartite(int[][] graph) {
color = new int[graph.length];
Arrays.fill(color, UNCOLORED);
for (int i = 0; i < graph.length ; i++) {//若染色失败则直接返回false
if (color[i] == UNCOLORED) { //当前结点还未染色
if (!dfs(i, RED, graph)){
return false;
}
}
}
return true;
}
private boolean dfs(int i, int currentColor, int[][] graph) {
//为当前节点染色
color[i] = currentColor;
//判断邻接结点应该染什么颜色
int neighborColor = currentColor == RED ? BLACK : RED;
//对邻居结点进行染色
for (int neighbor : graph[i]) {
if (color[neighbor] == UNCOLORED) {
if (!dfs(neighbor,neighborColor,graph)){
return false;
}
} else if (color[neighbor]==currentColor){//邻居已被染色,且和当前结点颜色相同则说明不是二分图,染色失败
return false;
}
}
return true;
}
}
这段代码的效率还是很高的。
广度优先遍历
接下来的代码引用自LeetCode官方题解,本人做题时只写了深度优先遍历。
class Solution {
private static final int UNCOLORED = 0;
private static final int RED = 1;
private static final int GREEN = 2;
private int[] color;
public boolean isBipartite(int[][] graph) {
int n = graph.length;
color = new int[n];
Arrays.fill(color, UNCOLORED);
for (int i = 0; i < n; ++i) {
if (color[i] == UNCOLORED) {
Queue<Integer> queue = new LinkedList<Integer>();
queue.offer(i);
color[i] = RED;
while (!queue.isEmpty()) {
int node = queue.poll();
int cNei = color[node] == RED ? GREEN : RED;
for (int neighbor : graph[node]) {
if (color[neighbor] == UNCOLORED) {
queue.offer(neighbor);
color[neighbor] = cNei;
} else if (color[neighbor] != cNei) {
return false;
}
}
}
}
}
return true;
}
}
本文地址:https://blog.csdn.net/First_C0de/article/details/107376849
下一篇: 用Java基础写数组的增删查改