2022.3.25 图论——判断二分图


一、今日刷题

1.题目

  1. 判断二分图

跳转LeetCode

存在一个 无向图 ,图中有 n 个节点。其中每个节点都有一个介于 0 到 n - 1 之间的唯一编号。给你一个二维数组 graph ,其中 graph[u] 是一个节点数组,由节点 u 的邻接节点组成。形式上,对于 graph[u] 中的每个 v ,都存在一条位于节点 u 和节点 v 之间的无向边。该无向图同时具有以下属性:

不存在自环(graph[u] 不包含 u)。
不存在平行边(graph[u] 不包含重复值)。
如果 v 在 graph[u] 内,那么 u 也应该在 graph[v] 内(该图是无向图)
这个图可能不是连通图,也就是说两个节点 u 和 v 之间可能不存在一条连通彼此的路径。

二分图 定义:如果能将一个图的节点集合分割成两个独立的子集 A 和 B ,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,就将这个图称为 二分图 。

如果图是二分图,返回 true ;否则,返回 false 。

在这里插入图片描述


2.分析

参考文章

先得理解什么是二分图:

如果能将一个图的节点集合分割成两个独立的子集 A 和 B ,并使图中的每一条边的两个节点一个来自 A 集合,一个来自 B 集合,就将这个图称为 二分图 。

在这里插入图片描述

通俗地说:
用两种颜色将图中的所有顶点着色,且使得任意一条边的两个端点的颜色都不相同的图,称为二分图。

在这里插入图片描述
所以为了解决本题,题目的思路为遍历一遍图,一边遍历一边染色,看看能不能用两种颜色给所有节点染色,且相邻节点的颜色都不相同。

3.代码

答案代码:

package Graph;

/**
 * @author: LYZ
 * @date: 2022/3/25 19:29
 * @description: 785. 判断二分图
 */
public class IsBipartite {
    public static void main(String[] args) {
        int[][] graph = {{1, 0}, {2, 0}, {3, 1}, {3, 2}};
        IsBipartite isBipartite = new IsBipartite();
        boolean ans = isBipartite.isBipartite(graph);
        System.out.println(ans);
    }

    // 记录图是否符合二分图性质
    private boolean bipartite = true;
    // 记录图中节点的颜色,false 和 true 代表两种不同颜色
    //很巧妙,如果是我写,就直接声明颜色了
    private boolean[] color;
    // 记录图中节点是否被访问过
    private boolean[] visited;

    // 主函数,输入邻接表,判断是否是二分图
    public boolean isBipartite(int[][] graph) {
        int n = graph.length;
        color =  new boolean[n];
        visited =  new boolean[n];
        // 因为图不一定是联通的,可能存在多个子图,所以要把每个节点都作为起点进行一次遍历
        // ******如果发现任何一个子图不是二分图,整幅图都不算二分图
        for (int v = 0; v < n; v++) {
            if (!visited[v]) {
                traverse(graph, v);
            }
        }
        return bipartite;
    }

    // DFS 遍历框架
    private void traverse(int[][] graph, int v) {
        // 如果已经确定不是二分图了,就不用浪费时间再递归遍历了
        if (!bipartite) return;

        visited[v] = true;
        for (int w : graph[v]) {
            if (!visited[w]) {
                // 相邻节点 w 没有被访问过,那么应该给节点 w 涂上和节点 v 不同的颜色
                color[w] = !color[v];
                // 继续遍历 w
                traverse(graph, w);
            } else {
                // 相邻节点 w 已经被访问过
                // 根据 v 和 w 的颜色判断是否是二分图
                if (color[w] == color[v]) {
                    // 若相同,则此图不是二分图
                    bipartite = false;
                }
            }
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值