华为OD机试双机位C卷真题-红黑图(C/C++/Py/Java/Js/Go)

华为OD机试真题-红黑图

华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 100分题型

华为OD机试双机位C卷真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解

题目描述

总所周知红黑树时一种平衡树,它最突出的特性就是不能有两个相连的红色节点。那我们定义一个红黑图,也就是一张无向图中,每个节点可能是红黑两种颜色,但我们保证没有两个相邻的红色节点。

现在给一张未染色的无向图,只能染红黑两种颜色,问总共有多少种染色方案使得它成为一个红黑图。

输入描述

第一行输入M(图中节点数) N(边数)

后续N行格式为:V1 V2表示一个V1到V2的边。

数据范围:1 <= M <= 15,0 <= N <= M * 3,不能保证所有节点都是连通的。保证没有重边和自环。

输出描述

输出一个数字表示染色方案的个数。

用例1

输入

none 复制代码
4 4
1 2
2 4
3 4
1 3

输出

none 复制代码
7

说明

4个节点,4条边,1号节点和2号节点相连,

2号节点和4号节点相连,3号节点和4号节点相连,

1号节点和3号节点相连,

若想必须保证相邻两个节点不能同时为红色,总共7种方案。

用例2

输入

none 复制代码
3 3
1 2
1 3
2 3

输出

none 复制代码
4

用例3

输入

none 复制代码
4 3
1 2
2 3
3 4

输出

none 复制代码
8

用例4

输入

none 复制代码
4 3
1 2
1 3
2 3

输出

none 复制代码
8

题解

思路:暴力枚举,题目数据量比较少直接使用m <= 15直接顶点所有颜色状态分配状态然后判断是否合法。

  1. 通过顶点数量确定枚举范围 [0 ,2^m - 1]
  2. 枚举的值代表一种分配方案,举个例子假设当前m = 3 枚举值为3 对应二进制位 011,我们设定二进制为1代表分配为红色,0代表分配为白色。
  3. 对于每个枚举值,合法性判断就是判断当前方案是否将相邻边同时分配为红色。假设有一个边对应两个顶点分别为x y,枚举值为i,对应判断表达式为(i >> (x-1) & 1) == 1 && (i >> (y-1) & 1) == 1. 如果当前所有边的合法性判断都通过则结果 + 1.
  4. 输出枚举完所有方案的结果。

c++

c++ 复制代码
#include<iostream>
#include<vector>
#include<string>
#include <utility> 
#include <sstream>
#include<algorithm> 
#include<cmath>
using namespace std;

int main() {
    int n,m;
    // 节点 边
    cin >> m >> n;
    vector<pair<int, int>> edges(n);
    for (int i = 0; i < n; i++) {
        int x , y;
        cin >> x >> y;
        edges[i] = {x, y};
    }
    // 没有边所以说明每个节点都能取红或黑
    if (n == 0) {
        cout << pow(2, m);
        return 0;
    }
    
    int res = 0;
    // 保留枚举所有情况判断是否合法 二进制方式枚举 二进制对应位 1 代表取红 0 代表为 黑
    for (int i = 0; i < (int)pow(2,m); i++) {
        // 判断是否合法
        bool flag = true;
        for (int j = 0; j < n; j++) {
            int x = edges[j].first;
            int y = edges[j].second;
            // 是否相邻边同为红 
            if ((i >> (x-1) & 1) == 1 && (i >> (y-1) & 1) == 1) {
                flag = false;
                break;   
            }
        }
        if (flag) {
            res++;
        }
    }
    
    cout << res;
    return 0;
}

JAVA

JAVA 复制代码
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 节点数 m,边数 n
        int m = sc.nextInt();
        int n = sc.nextInt();
        int[][] edges = new int[n][2];
        for (int i = 0; i < n; i++) {
            edges[i][0] = sc.nextInt();
            edges[i][1] = sc.nextInt();
        }

        // 没有边,说明每个节点可以独立染色为红或黑
        if (n == 0) {
            System.out.println((int)Math.pow(2, m));
            return;
        }

        int res = 0;
        // 枚举所有染色情况,用二进制方式表示染色状态
        for (int i = 0; i < (1 << m); i++) {
            boolean flag = true;
            for (int[] edge : edges) {
                int x = edge[0], y = edge[1];
                // 相邻节点不能同时为红色(即都为1)
                if (((i >> (x - 1)) & 1) == 1 && ((i >> (y - 1)) & 1) == 1) {
                    flag = false;
                    break;
                }
            }
            if (flag) res++;
        }
        System.out.println(res);
    }
}

Python

python 复制代码
# 节点数 m,边数 n
m, n = map(int, input().split())
edges = [tuple(map(int, input().split())) for _ in range(n)]

# 没有边,每个节点可红或黑,共2^m种方案
if n == 0:
    print(2 ** m)
    exit()

res = 0
# 枚举所有染色情况,1表示红色,0表示黑色
for i in range(1 << m):
    valid = True
    for x, y in edges:
        if (i >> (x - 1)) & 1 and (i >> (y - 1)) & 1:
            valid = False
            break
    if valid:
        res += 1

print(res)

JavaScript

js 复制代码
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let inputLines = [];

rl.on('line', (line) => {
    inputLines.push(line);
}).on('close', () => {
    const [m, n] = inputLines[0].split(' ').map(Number); // 读取节点数和边数
    const edges = inputLines.slice(1).map(line => line.split(' ').map(Number));

    if (n === 0) {
        console.log(2 ** m);  // 没有边,2^m 种方案
        return;
    }

    let res = 0;
    // 用二进制枚举所有染色方案
    for (let i = 0; i < (1 << m); i++) {
        let valid = true;
        for (const [x, y] of edges) {
            // 判断相邻节点是否都为红色(用1表示红色)
            if (((i >> (x - 1)) & 1) && ((i >> (y - 1)) & 1)) {
                valid = false;
                break;
            }
        }
        if (valid) res++;
    }

    console.log(res);
});

Go

go 复制代码
package main

import (
	"fmt"
)

func main() {
	var m, n int
	fmt.Scan(&m, &n)

	edges := make([][2]int, n)
	for i := 0; i < n; i++ {
		fmt.Scan(&edges[i][0], &edges[i][1])
	}

	// 没有边,每个节点可以红或黑,总共 2^m 种方案
	if n == 0 {
		fmt.Println(1 << m)
		return
	}

	res := 0
	// 枚举所有染色方案,1 表示红色
	for i := 0; i < (1 << m); i++ {
		valid := true
		for _, edge := range edges {
			x, y := edge[0], edge[1]
			if ((i>>(x-1))&1) == 1 && ((i>>(y-1))&1) == 1 {
				valid = false
				break
			}
		}
		if valid {
			res++
		}
	}

	fmt.Println(res)
}

C语言

cpp 复制代码
#include <stdio.h>
#include <math.h>

#define MAXN 100

// 定义边结构体 
typedef struct {
    int x;
    int y;
} Edge;

int main() {
    int n, m;
    // 节点 边
    scanf("%d %d", &m, &n);

    Edge edges[MAXN];

    for (int i = 0; i < n; i++) {
        scanf("%d %d", &edges[i].x, &edges[i].y);
    }

    // 没有边所以说明每个节点都能取红或黑
    if (n == 0) {
        // pow返回double,这里强转为int
        printf("%d", (int)pow(2, m));
        return 0;
    }

    int res = 0;

    // 保留枚举所有情况判断是否合法
    // 二进制方式枚举 二进制对应位 1 代表取红 0 代表为黑
    int total = (int)pow(2, m);

    for (int i = 0; i < total; i++) {
        // 判断是否合法
        int flag = 1;

        for (int j = 0; j < n; j++) {
            int x = edges[j].x;
            int y = edges[j].y;

            // 是否相邻边同为红
            if (((i >> (x - 1)) & 1) == 1 && ((i >> (y - 1)) & 1) == 1) {
                flag = 0;
                break;
            }
        }

        if (flag) {
            res++;
        }
    }

    printf("%d", res);

    return 0;
}
相关推荐
无限码力4 小时前
华为OD机试双机位C卷-用户入网定期复评(C/C++/Py/Java/Js/Go)
华为od·华为od机试真题·华为od机试双机位c卷·华为od上机考试真题·华为od机考真题·华为od-用户入网定期复评
gis分享者1 天前
华为OD面试-Java、C++、Pyhton等多语言实现-目录
java·c++·华为od·面试·目录·od·机试
无限码力2 天前
华为OD机试双机位C卷-虚拟文件系统(C/C++/Py/Java/Js/Go)
华为od·华为od机试真题·华为od机试双机位c卷·华为od上机考试真题·华为od机考真题·华为od-虚拟文件系统·华为od机试题库
sprite_雪碧4 天前
考研机试笔记-1输入输出
笔记·考研·华为od
无限码力8 天前
华为OD机试真题2026双机位C卷 C++实现【日志解析】
c++·华为od·华为od机试真题·华为od机考真题·华为od机试真题-日志解析
uesowys11 天前
华为OD算法开发指导-数据结构-图
数据结构·算法·华为od
快敲啊死鬼14 天前
机试day5
算法·华为od·华为
LqKKsNUdXlA1 个月前
Comsol冻土水热力耦合模型代做 可复现白青波,秦晓同模型 建立了路基水热耦合计算控制方程
华为od
开开心心_Every1 个月前
剪切板工具存500条,可搜索备份导入导出
linux·运维·服务器·华为od·edge·pdf·华为云