二分图/二部图检测(动图&代码实现)

爱⌒轻易说出口 提交于 2019-12-05 12:44:04

定义

二分图(中文翻译问题,有时也称作二部图),是图论中的一种特殊模型。 如果图可以分为两部分: 绿色和蓝色,并且每一条连线都连接着一个绿色顶点和一个蓝色定点,则称这个图为一个二分图.下图就是一个二分图. 二分图

二分图检测

示例图,如下: 示例图 肉眼很难区分出两部分,需要采用一定的算法才可区分,下面就介绍检测的方法--染色.

染色

首先,选择一个节点,置为蓝色(绿色也可),再将与之连线的节点置为对立的颜色-绿色,按深度优先(广度优先也可)的逻辑,将节点依次置为对立色,如果最终结果为:每条边都连接这一个蓝色和一个绿色节点,则二分图检测成功. 染色动图

代码实现(java)

import java.util.ArrayList;

public class BipartitionDetection {

    /**
     * 图的类
     * public class Graph {
     * private int V; // 顶点
     * private TreeSet<Integer>[] adj; // 每个顶点相连的顶点树数组
     * }
     */
    private Graph G;
    /**
     * 已访问的顶点数组
     */
    private boolean[] visited;
    /**
     * 0->蓝色, 1->绿色
     */
    private int[] colors;
    /**
     * 是否为二分图
     */
    private boolean isBipartite = true;

    public BipartitionDetection(Graph G) {
        this.G = G;
        visited = new boolean[G.V()];
        colors = new int[G.V()];
        for (int i = 0; i < G.V(); i++)
            // 初始化
            colors[i] = -1;

        for (int v = 0; v < G.V(); v++)
            if (!visited[v])
                if (!dfs(v, 0)) {
                    isBipartite = false;
                    break;
                }
    }

    /**
     * 递归遍历节点
     *
     * @param v     顶点
     * @param color 颜色,0->蓝色, 1->绿色
     */
    private boolean dfs(int v, int color) {
        visited[v] = true;
        colors[v] = color;
        // 遍历与v相连的每一个顶点
        for (int w : G.adj(v))
            // 判断是否遍历过/染过色
            if (!visited[w]) {
                // 染为与v对立的颜色
                if (!dfs(w, 1 - color)) return false;
            } else if (colors[w] == colors[v]) {
                // 已染色,判断与v相连的顶点颜色是否与v相同,若相同,则不满足二分图
                return false;
            }
        return true;
    }

    /**
     * 是否为二分图
     */
    public boolean isBipartite() {
        return isBipartite;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!