
华为OD机试 2024E卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
给一个 无向图染色,可以填红黑两种颜色,必须保证相邻的两个节点不能同时为红色,输出有多少种不同的染色方案?
二、输入描述
第一行输入M(图中节点数) N(边数)
后续N行格式为:V1 V2表示一个V1到V2的边。
数据范围:1 <= M <= 15, 0 <= N <= M * 3, 不能保证所有节点都是连通的。
三、输出描述
输出一个 数字 表示染色方案的个数。
说明
0 < N < 15
 0 <= M <= N * 3
 0 <= s, t < n
不保证图连通
 保证没有重边和自环
四、测试用例
测试用例1:
1、输入
4 4
 1 2
 2 4
 3 4
 1 3
2、输出
7
3、说明
4个节点,4条边,1号节点和2号节点相连,
 2号节点和4号节点相连,3号节点和4号节点相连,
 1号节点和3号节点相连,
 若想必须保证相邻两个节点不能同时为红色,总共7种方案。
测试用例2:
1、输入
3 0
2、输出
8
3、说明
没有任何边,所有节点可以自由染色。每个节点有2种选择,总共2^3=8种方案。
五、解题思路
题目要求在一个无向图中,用红色和黑色两种颜色对节点进行染色,且相邻的两个节点不能同时为红色。我们需要计算满足条件的不同染色方案的总数。
数据结构与算法选择
邻接表(Adjacency List):由于节点数较小(M ≤ 15),可以使用一个整数数组 adjacency 来表示每个节点的邻接关系。每个元素 adjacency[i] 用二进制位来表示节点 i 的邻居,方便进行位运算。
枚举所有子集(Bitmasking):由于节点数不超过15,可以通过枚举所有可能的节点子集(即所有可能的染色方案)来解决问题。每个子集对应一种将某些节点染为红色,其余染为黑色的方案。
验证独立集:对于每个子集,检查其中是否存在相邻的两个节点都被染为红色。如果不存在,则该子集对应的染色方案是有效的。
六、Python算法源码
# Python 代码实现
import sys
def main():
    import sys
    import math
    # 读取输入的所有内容并按行分割
    input = sys.stdin.read().split()
    idx = 0
    # 读取节点数M和边数N
    M = int(input[idx])
    idx += 1
    N = int(input[idx])
    idx += 1
    # 初始化邻接表,使用位掩码表示每个节点的邻居
    adjacency = [0] * M
    # 读取N条边,并构建邻接表
    for _ in range(N):
        V1 = int(input[idx]) - 1  # 转为0-based索引
        idx += 1
        V2 = int(input[idx]) - 1
        idx += 1
        adjacency[V1] |= (1 << V2)  # 将V2加入V1的邻居
        adjacency[V2] |= (1 << V1)  # 将V1加入V2的邻居
    # 初始化有效染色方案的计数
    count = 0
    total = 1 << M  # 计算2^M种染色方案
    # 遍历所有可能的染色方案
    for s in range(total):
        valid = True  # 标记当前方案是否有效
        for i in range(M):
            if ((s >> i) & 1) == 1:  # 如果节点i被染为红色
                if (s & adjacency[i]) != 0:  # 检查相邻节点是否也被染为红色
                    valid = False  # 当前方案无效
                    break  # 跳出内层循环
        if valid:
            count += 1  # 有效方案计数加一
    # 输出结果
    print(count)
# 调用主函数
if __name__ == "__main__":
    main()
七、JavaScript算法源码
// JavaScript 代码实现
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
let input = [];
rl.on('line', function(line){
    input = input.concat(line.trim().split(/\s+/));
}).on('close', function(){
    let idx = 0;
    // 读取节点数M和边数N
    const M = parseInt(input[idx++]);
    const N = parseInt(input[idx++]);
    // 初始化邻接表,使用位掩码表示每个节点的邻居
    const adjacency = new Array(M).fill(0);
    // 读取N条边,并构建邻接表
    for(let i = 0; i < N; i++){
        const V1 = parseInt(input[idx++]) - 1; // 转为0-based索引
        const V2 = parseInt(input[idx++]) - 1;
        adjacency[V1] |= (1 << V2); // 将V2加入V1的邻居
        adjacency[V2] |= (1 << V1); // 将V1加入V2的邻居
    }
    let count = 0;
    const total = 1 << M; // 计算2^M种染色方案
    // 遍历所有可能的染色方案
    for(let s = 0; s < total; s++){
        let valid = true; // 标记当前方案是否有效
        for(let i = 0; i < M; i++){
            if( ((s >> i) & 1) === 1 ){ // 如果节点i被染为红色
                if( (s & adjacency[i]) !== 0 ){ // 检查相邻节点是否也被染为红色
                    valid = false; // 当前方案无效
                    break; // 跳出内层循环
                }
            }
        }
        if(valid){
            count++; // 有效方案计数加一
        }
    }
    // 输出结果
    console.log(count);
});
八、C算法源码
// C 语言代码实现
#include <stdio.h>
int main(){
    int M, N;
    // 读取节点数M和边数N
    if(scanf("%d %d", &M, &N)!=2){
        return 0;
    }
    // 初始化邻接表,使用位掩码表示每个节点的邻居
    int adjacency[M];
    for(int i=0;i<M;i++){
        adjacency[i] = 0;
    }
    // 读取N条边,并构建邻接表
    for(int i=0;i<N;i++){
        int V1, V2;
        if(scanf("%d %d", &V1, &V2)!=2){
            return 0;
        }
        V1 -= 1; // 转为0-based索引
        V2 -= 1;
        adjacency[V1] |= (1 << V2); // 将V2加入V1的邻居
        adjacency[V2] |= (1 << V1); // 将V1加入V2的邻居
    }
    int count = 0;
    int total = 1 << M; // 计算2^M种染色方案
    // 遍历所有可能的染色方案
    for(int s=0; s < total; s++){
        int valid = 1; // 标记当前方案是否有效
        for(int i=0; i < M; i++){
            if( ((s >> i) & 1) == 1 ){ // 如果节点i被染为红色
                if( (s & adjacency[i]) != 0 ){ // 检查相邻节点是否也被染为红色
                    valid = 0; // 当前方案无效
                    break; // 跳出内层循环
                }
            }
        }
        if(valid){
            count++; // 有效方案计数加一
        }
    }
    // 输出结果
    printf("%d\n", count);
    return 0;
}
九、C++算法源码
// C++ 代码实现
#include <bits/stdc++.h>
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int M, N;
    // 读取节点数M和边数N
    cin >> M >> N;
    // 初始化邻接表,使用位掩码表示每个节点的邻居
    vector<int> adjacency(M, 0);
    // 读取N条边,并构建邻接表
    for(int i=0; i<N; i++){
        int V1, V2;
        cin >> V1 >> V2;
        V1 -= 1; // 转为0-based索引
        V2 -= 1;
        adjacency[V1] |= (1 << V2); // 将V2加入V1的邻居
        adjacency[V2] |= (1 << V1); // 将V1加入V2的邻居
    }
    int count = 0;
    int total = 1 << M; // 计算2^M种染色方案
    // 遍历所有可能的染色方案
    for(int s=0; s < total; s++){
        bool valid = true; // 标记当前方案是否有效
        for(int i=0; i < M; i++){
            if( ((s >> i) & 1) == 1 ){ // 如果节点i被染为红色
                if( (s & adjacency[i]) != 0 ){ // 检查相邻节点是否也被染为红色
                    valid = false; // 当前方案无效
                    break; // 跳出内层循环
                }
            }
        }
        if(valid){
            count++; // 有效方案计数加一
        }
    }
    // 输出结果
    cout << count << "\n";
    return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。













![[uni-app]小兔鲜-06地址+sku+购物车](https://img-blog.csdnimg.cn/img_convert/234f86a989fee0af08e1601374fc44da.png)






