给定一个由n个点,m条边组成的无向图(注意,此图可能不连通),对任意1 ≤ i ≤ m存在一条边连接u[i], v[i]。回答此图是不是二分图。二分图定义为存在一种给图中每一个点染上黑白两色其中之一的着色方式,使得对每一对有边直接相连的点颜色不同。
第一行输入为N和M,代表无向图的点数和边数。
接下来M行,表示M条边,每一行两个整数u[i], v[i],满足1 ≤ u[i], v[i] ≤ n,保证图中无重边,自环。
其中保证1 ≤ N, M ≤ 100000
一行字符串,为Yes,或者No。
Yes表示输入图是二分图。
No表示输入图不是二分图。
5 7 1 2 2 3 3 4 4 1 4 5 5 2
Yes
如图,把1, 3, 5点染色为白,2, 4染色为黑,即可满足二分图要求,所以这个图是二分图。
5 4 1 2 2 3 3 1 4 5
No
1, 2, 3号点无论如何染色都无法满足要求,所以不是二分图。
import java.util.*; import static java.lang.System.in; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(in); int n = sc.nextInt(); int m = sc.nextInt(); // 建图 HashMap<Integer, HashSet<Integer>> graph =new HashMap<>(); for(int i = 0; i<m; i++){ int curr = sc.nextInt(); int next = sc.nextInt(); graph.putIfAbsent(curr,new HashSet()); graph.get(curr).add(next); } // 是n+1,因为从0开始 int[] colors = new int[n+1]; // 我们染色三种情况,0是没有染色到,1是一种颜色,-1是一种颜色 boolean ans = true; for(int cur= 1; cur<=n; cur++){ //对于一个从来没染过色的点,初始都为1,然后我们开始爱的魔力找圈圈 if(colors[cur] == 0 && !dfs(colors,1,graph, cur )) ans =false; } //***改的,就是为了输出简单 String res = "Yes"; if(!ans) res = "No"; System.out.println(res); } private static boolean dfs(int[] colors, int color, HashMap<Integer, HashSet<Integer>> graph,int cur){ //找到了一个环,然后看他现在要给的颜色和之前的颜色是不是一样的。这个根据题意好理解。 if(colors[cur] != 0) return colors[cur] == color; colors[cur] = color; //非连通图的情况,到了尾巴,发现他是个一条边,这种情况肯定是对的 if(!graph.containsKey(cur)) return true; for(int next: graph.get(cur)){ if(!dfs(colors, -color, graph, next)) return false; } return true; } }