无向图染色

华为od机试

题目描述

给一个无向图染色,可以填红黑两种颜色,必须保证相邻两个节点不能同时为红色,输出有多少种不同的染色方案?

输入描述

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

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

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

输出描述

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

示例1

输入:
4 4
1 2
2 4
3 4
1 3

输出:
7

说明:
4个节点,4条边,1号节点和2号节点相连,
2号节点和4号节点相连,3号节点和4号节点相连,
1号节点和3号节点相连,
若想必须保证相邻两个节点不能同时为红色,总共7种方案。

示例2

输入:
3 3
1 2
1 3
2 3

输出:
4

示例3

输入:
4 3
1 2
2 3
3 4

输出:
8

示例4

输入:
4 3
1 2
1 3
2 3

输出:
8

题解

题目类型:

这道题目属于 位运算枚举 类型的题目,结合了图的染色问题,主要通过枚举所有可能的染色方案来判断是否满足约束条件。

解题思路:

  1. 题目理解
    • 给定一个无向图,图中的每个节点要么是红色,要么是黑色,且相邻的两个节点不能同时为红色。
    • 需要计算出图中满足染色条件的所有方案的个数。
  2. 枚举所有可能的染色方案
    • 假设有 m 个节点,那么可以用一个二进制数表示所有节点的颜色方案。
      • 二进制数的每一位表示一个节点的颜色(0 为黑色,1 为红色)。
      • 例如,对于 m = 3,染色方案可以是:
        • 000(黑色、黑色、黑色)
        • 001(黑色、黑色、红色)
        • 010(黑色、红色、黑色)
        • 111(红色、红色、红色)等。
  3. 检查染色是否合法
    • 对于每一个染色方案,检查是否满足相邻节点不能同时为红色的约束。
    • 如果满足条件,则增加计数。
  4. 算法实现
    • 使用一个二进制数表示每一个染色方案,遍历从 02^m - 1 的所有可能的方案。
    • 对每一个染色方案,通过位运算提取节点的颜色,检查相邻节点的颜色是否满足条件。

代码大致描述:

  1. 输入
    • 输入包括节点数 m 和边数 n,接着输入 n 条边,每条边表示一对相邻的节点。
  2. 检查染色方案的有效性
    • 对于每个染色方案,检查相邻的节点是否满足约束:即相邻两个节点不能同时为红色(即二进制表示中对应位不能同时为1)。
  3. 输出
    • 输出符合要求的染色方案的个数。

时间复杂度:

  • 时间复杂度

    • 我们枚举所有的染色方案,染色方案的总数为 2^m(即 1 << m)。

    • 对于每一个染色方案,我们需要检查所有的边(即 n 条边),对于每条边,需要进行常数时间的操作(位运算)。因此,时间复杂度为:

      • 由于 m 最大为 15,因此 2^m 最多为 32768,n 最大为 m * 3 = 45,所以时间复杂度在最坏情况下是 ,即最多约为 1.5 million 次操作,足够在合理时间内完成。
  • 空间复杂度

  • 存储图的边需要 O(n) 的空间。

    • 存储染色方案和结果需要 O(1) 空间,除去输入和输出。
  • 因此,空间复杂度是 O(n)

C++

#include <bits/stdc++.h>

using namespace std;

bool check(vector<pair<int, int>> &edges, int plan) {
    //举例: plan 3(二进制:0011) 表示 1,2 号节点为红色, 3,4 号节点黑色
    for (const auto [v1, v2]: edges) {
        int c1 = (plan >> (v1 - 1)) & 1;  // 找到第 v1 为的染色值
        int c2 = (plan >> (v2 - 1)) & 1;  // 找到第 v2 为的染色值
        // 必须保证相邻两个节点不能同时为红色
        if (c1 + c2 == 2) return false;
    }

    return true;
}

int main() {
    int m, n;
    cin >> m >> n;
    // 读取 n 条  V1 到 V2 的边, 存储到 edges
    vector<pair<int, int>> edges(n);
    for (int i = 0; i < n; i++) {
        cin >> edges[i].first >> edges[i].second;
    }

    int count = 0;
    // 用二进制位来枚举所有的染色情况,然后统计可行的染色计划
    for (int plan = 0; plan <= (1 << m) - 1; plan++) {
        if (check(edges, plan)) count++;
    }

    cout << count << endl;

    return 0;
}

希望这个专栏能让您熟练掌握算法, 🎁🎁🎁 立即订阅

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

#面经##春招##秋招##华为od##C++#
C++笔试真题题解 文章被收录于专栏

笔试真题题解

全部评论
点赞 回复 分享
发布于 04-22 14:12 湖北

相关推荐

面试体验是很棒的,面试官都非常准时,面试过程中也会去引导,会沿着你的回答继续去问自我介绍项目介绍项目中提到的线程池干什么用的?还有什么创建线程池的方法?线程池的核心参数。拒绝策略?线程池收到任务后执行流程?如果请求量比较大怎么调参数?项目中&nbsp;ConcurrentHashMap&nbsp;干什么用的?为什么要用他别的不行吗?如果不用他你会怎么实现?介绍项目中对接ai生成可视化图表。项目中用&nbsp;ThreadLocal&nbsp;做什么的?知道&nbsp;ThreadLocal的内存泄露问题吗?为什么要把key设置为弱引用?&nbsp;ThreadLocal底层是怎么实现的?为什么要用Redis作缓存?Redis为什么快?Redis雪崩和击穿问题。Redis大key问题。如果让你来设计你会用什么思路解决?除了缓存Redis还能干什么?用过Redis当消息队列吗?为什么不如MQ?刚刚提到Redis持久化机制,介绍一下。聊了聊笔试的第三题派对男女匹配问题说一下常见的排序算法,手撕归并介绍jvm垃圾回收算法。怎么判断对象是否是垃圾?假如你项目上线后突然有个功能出现故障了,要怎么办?之后就聊了聊学校学习的一些事,如果要学习新知识会怎么学?看视频还是看文章?怎么做技术选型的?问了下个人优点,有没有考研打算,为什么不考研?之前参加过多少面试?准备面试多久了?平时会去背八股吗?那如果遇到八股没背到的东西怎么回答呢?
查看16道真题和解析
点赞 评论 收藏
分享
07-04 17:30
东华大学 Java
约的下午四点面试,3:50到的,让我等了45分钟,说面试官在开会😀终于来了以后先整了个Ai语音转文字,在我自我介绍过程中多次看手机回消息和同事搭话,这个时候我已经想走人了,失眠一晚上,上午面了两场,中午又吃坏肚子肠胃炎,还打车50块钱来的,已经憋了一肚子气了。上来问我研究生课题做了什么,具体怎么做的,用什么算法,介绍完以后说详细点,再详细点,说完以后让再详细点,被问的烦了就说不方便说,课题组自研算法,不方便继续透漏。还在追问,问我发paper没,能不能搜到,准备搜一下看看。阴阳怪气说就你们这还保密呢,最后说对你们的项目不感兴趣只是想考验解决问题的能力,耸了耸肩说没想到你们这还保密然后是问八股,很常规,数据类型,关键字,equals和==,泛型,try-catch-final,sql事务,反射,反序列化,快排,冒泡,死锁,设计模式。有一些没答上来,确实我复习的还是不到位我承认好了,他开始了,问我究竟有没有学过Java,说对我的学历和能力存疑,说这不都是基础吗?还说瞧不起那些刷题背八股的,觉得都是为了应付。问我期望薪资我说10k,他说可以压吗?觉得我拿不到这个价。然后他的原话“你现在的处境很为难,我的处境也很为难,一方面你学的一般,我不知道你本科和研究生在干什么,另一方面我又想拉你一把给你个机会,但我还需要犹豫犹豫,再考虑考虑你。”面试全程拿个电脑在那噼里啪啦的敲键盘,头也不抬,还看手机,把我贬的一文不值😆ps:上海云简业业财
查看17道真题和解析
点赞 评论 收藏
分享
评论
4
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务