图着色就是简单的dfs

dfs是否有环

直接用visited[]数组

bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
    // 每个节点用dfs查环
    vector<vector<int>> graph(numCourses);
    for (const auto &edge : prerequisites) {
        graph[edge[1]].push_back(edge[0]);
    }
    vector<bool> visited(numCourses);
    for (int i = 0; i < numCourses; i++) {
        if (hasCycle(i, graph, visited)) return false;
    }
    return true;
}

bool hasCycle(int u, const vector<vector<int>> &graph, vector<bool> &visited) {
    if (visited[u]) return true;
    visited[u] = true;
    for (int v : graph[u]) {
        if (hasCycle(v, graph, visited)) return true;
    }
    visited[u] = false;
    return false;
}

或者,用color[]数组表示各节点颜色(状态):{ UNVISITED, VISITING, VISITED }。如果已着色(!=UNVISITED),在dfs开头就能判断是否有环(==VISITING)。访问邻接点前把当前节点设为VISITING,访问后把当前节点设为VISITED。

bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
    // 每个节点用dfs查环,即dfs时遇到标记为VISITING的节点
    // 0: UNVISITED, 1: VISITING, 2: VISITED
    vector<vector<int>> graph(numCourses);
    for (const auto &edge : prerequisites) {
        graph[edge[1]].push_back(edge[0]);
    }
    vector<int> color(numCourses, 0);
    for (int i = 0; i < numCourses; i++) {
        if (hasCycle(i, graph, color)) return false;
    }
    return true;
}

bool hasCycle(int u, const vector<vector<int>> &graph, vector<int> &color) {
    if (color[u] != 0) return color[u] == 1;
    color[u] = 1;
    for (int v : graph[u]) {
        if (hasCycle(v, graph, color)) return true;
    }
    color[u] = 2;
    return false;
}

是否二分图

dfs或bfs遍历着色。当前节点若已着色,看它是不是希望的颜色就能判断是否二分。若未着色,着色后再看邻接点。

bool isBipartite(vector<vector<int>>& graph) {
    const int N = graph.size();
    vector<int> color(N, -1);
    for (int i = 0; i < N; i++) {
        if (color[i] == -1 && !canColor(i, 0, graph, color)) return false;
    }
    return true;
}

bool canColor(int node, int c, vector<vector<int>> &graph, vector<int> &color) {
    if (color[node] != -1) return color[node] == c;
    color[node] = c;
    for (int neighbor : graph[node]) {
        if (!canColor(neighbor, 1 - c, graph, color)) return false;
    }
    return true;
}

m着色:能否用最多m种颜色着色

// 回溯法:对[k,..]顶点完成m着色,0<=k<V
bool graphColoring(int k, int m, int color[], bool G[V][V]) {
    if (k == V) return true;
    for (int c = 0; c < m; c++) {
        if (canColor(k, c, color, G)) {
            color[k] = c;
            if (graphColoring(k + 1, m, color, G)) return true;
            color[k] = -1;
        }
    }
    return false;
}

// 能否对顶点k着c色,要看k的邻接点有没有已着c色的
bool canColor(int k, int c, int color[], bool G[V][V]) {
    for (int i = 0; i < V; i++) {
        if (G[k][i] && color[i] == c) { // 看k的邻居节点i
            return false;
        }
    }
    return true;  
}