染色法判别二分图

136 阅读1分钟

Snipaste_2023-03-18_15-25-37.png

  • 时间复杂度是 O(n+m), n表示点数,m 表示边数

模板

  • C++
int n;      // n表示点数
int h[N], e[M], ne[M], idx;     // 邻接表存储图
int color[N];       // 表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色

// 参数:u表示当前节点,c表示当前点的颜色
bool dfs(int u, int c)
{
    color[u] = c;
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (color[j] == -1)
        {
            if (!dfs(j, !c)) return false;
        }
        else if (color[j] == c) return false;
    }

    return true;
}

bool check()
{
    memset(color, -1, sizeof color);
    bool flag = true;
    for (int i = 1; i <= n; i ++ )
        if (color[i] == -1)
            if (!dfs(i, 0))
            {
                flag = false;
                break;
            }
    return flag;
}
  • Java
public static int[] h = new int[N];
public static int[] e = new int[M];
public static int[] ne = new int[M];
public static int[] color = new int[N];  // 表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色

//判断是不是二分图,是的话返回true,不是返回false
public static boolean[] check() {
    //初始化
    Arrays.fill(color, -1);
    boolean flag = true;
    
    for (int i = 1; i <= n; i++) {
        //如果该点没有被染色
        if (color[i] == -1) {
            //dfs染色,并判断是否染色成功
            if (!dfs(i, 0)) {
                flag = false;
                break;
            }
        }
    }
    return flag;
}

// 参数:u表示当前节点,c表示当前点的颜色
public static boolean dfs(int u, int c) {
    //先给点染上色
    color[u] = c;
    //遍历与该点相连的每一个点
    for (int i = h[u]; i != -1; i = ne[i]) {
        //先记录相邻点
        int j = e[i];
        //如果相邻点没有被染色
        if (color[j] == -1) {
            //dfs染上相对的颜色,并判断是否染色成功
            if (!dfs(j, 1 - c)) {
                return false;
            }
        } else if (color[j] == c) {
            return false;
        }
    }
    return true;
}

练习

01 染色法判定二分图

  • 题目

Snipaste_2023-03-18_15-23-19.png

  • 题解
import java.io.*;
import java.util.Arrays;

public class Main {
    public static final int N = 100010;
    public static final int M = N * 2;
    public static int[] h = new int[N];
    public static int[] e = new int[M];
    public static int[] ne = new int[M];
    public static int[] color = new int[N];  // 表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色
    public static int n, m, idx;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));
        String[] str1 = br.readLine().split(" ");
        n = Integer.parseInt(str1[0]);
        m = Integer.parseInt(str1[1]);
        Arrays.fill(h, -1);
        idx = 0;
        while (m-- > 0) {
            String[] str2 = br.readLine().split(" ");
            int u = Integer.parseInt(str2[0]);
            int v = Integer.parseInt(str2[1]);
            add(u, v);
            add(v, u);
        }

        if (check()) {
            pw.println("Yes");
        } else {
            pw.println("No");
        }
        br.close();
        pw.close();
    }

    public static void add(int a, int b) {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }

    //判断是不是二分图,是的话返回true,不是返回false
    public static boolean check() {
        //初始化
        Arrays.fill(color, -1);
        boolean flag = true;

        for (int i = 1; i <= n; i++) {
            //如果该点没有被染色
            if (color[i] == -1) {
                //dfs染色,并判断是否染色成功
                if (!dfs(i, 0)) {
                    flag = false;
                    break;
                }
            }
        }
        return flag;
    }

    // 参数:u表示当前节点,c表示当前点的颜色
    public static boolean dfs(int u, int c) {
        //先给点染上色
        color[u] = c;

        //遍历与该点相连的每一个点
        for (int i = h[u]; i != -1; i = ne[i]) {
            //先记录相邻点
            int j = e[i];
            //如果相邻点没有被染色
            if (color[j] == -1) {
                //dfs染上相对的颜色,并判断是否染色成功
                if (!dfs(j, 1 - c)) {
                    return false;
                } 
            } else if (color[j] == c) {  //如果相邻点的颜色相同,不是二分图,返回false
                return false;
            }
        }
        return true;
    }
}