news 2026/4/16 19:10:49

PTA刷题实战:图着色问题(C++邻接表+集合判重)保姆级代码解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PTA刷题实战:图着色问题(C++邻接表+集合判重)保姆级代码解析

PTA刷题实战:图着色问题(C++邻接表+集合判重)保姆级代码解析

最近在PTA刷题时遇到一道经典的图着色问题,题目要求判断给定的颜色分配方案是否满足图着色问题的解。这道题看似简单,但实现过程中有不少细节需要注意。今天我就来分享一下我的解题思路和代码实现,希望能帮助到正在准备PAT/PTA考试或算法竞赛的朋友们。

1. 问题分析与数据结构选择

图着色问题的核心在于判断相邻顶点是否颜色相同。首先我们需要明确题目要求:

  • 给定无向图G=(V,E)
  • 判断给定的颜色分配方案是否满足:
    1. 使用的颜色数量恰好为K种
    2. 任意两个相邻顶点颜色不同

对于数据结构的选择,邻接表是最适合表示稀疏图的结构。相比邻接矩阵,邻接表在空间复杂度上更有优势(O(V+E) vs O(V²)),特别适合顶点数较多但边数相对较少的图。

vector<int> g[1010]; // 邻接表存储图结构

这里我选择使用vector数组来构建邻接表,因为:

  • 动态数组方便添加边
  • 随机访问效率高
  • 内存管理由STL自动处理

2. 输入处理与图构建

题目输入分为几个部分:

  1. 顶点数V、边数E和颜色数K
  2. E条边的信息
  3. N个待检查的颜色分配方案
int v, e, k; cin >> v >> e >> k; // 构建邻接表 for (int i = 1; i <= e; i++) { int x, y; cin >> x >> y; g[x].push_back(y); g[y].push_back(x); // 无向图需要双向添加 }

注意:无向图的边需要在邻接表中双向添加,即如果顶点A与B相连,既要在A的邻接表中添加B,也要在B的邻接表中添加A。

3. 颜色分配方案检查

对于每个颜色分配方案,我们需要进行两个主要检查:

3.1 颜色种类数检查

使用STL中的set容器可以方便地统计不同颜色的数量:

set<int> s; // 用于存储不同颜色 int c[1010]; // 存储每个顶点的颜色 // 读取颜色分配 for (int i = 1; i <= v; i++) { cin >> c[i]; s.insert(c[i]); } // 检查颜色数量 if (s.size() != k) { cout << "No\n"; continue; }

set的insert操作会自动去重,size()方法直接返回不同颜色的数量,非常高效。

3.2 相邻顶点颜色检查

这是问题的核心检查部分,需要遍历每个顶点及其所有邻接点:

int f = 0; // 标记是否发现冲突 for (int i = 1; i <= v; i++) { for (int j = 0; j < g[i].size(); j++) { if (c[i] == c[g[i][j]]) { f = 1; break; } } if (f) break; }

这里有几个优化点:

  1. 一旦发现冲突立即跳出循环,避免不必要的检查
  2. 外层循环从1到v,内层循环遍历每个顶点的邻接表
  3. 使用标记变量f来记录检查结果

4. 常见错误与调试技巧

在实现过程中,我遇到过几个典型的错误:

  1. 数组越界:顶点编号从1开始,但数组大小设置不足

    • 解决方法:将数组大小设置为略大于最大顶点数(如1010)
  2. 邻接表构建错误:忘记无向图需要双向添加边

    • 解决方法:添加边时同时处理g[x].push_back(y)和g[y].push_back(x)
  3. 颜色数量判断错误:直接统计颜色数组中的不同值

    • 解决方法:使用set自动去重统计
  4. 边界条件处理不当:如K=1时所有顶点必须同色但不相邻

    • 解决方法:单独测试极端情况

调试时可以添加临时输出语句检查中间结果:

// 调试输出邻接表 for (int i = 1; i <= v; i++) { cout << "顶点" << i << "的邻接点: "; for (int j = 0; j < g[i].size(); j++) { cout << g[i][j] << " "; } cout << endl; }

5. 性能优化与代码风格

考虑到PTA的评判系统对时间和空间有限制,我们需要注意:

  1. 输入输出效率:使用cin/cout时,可以添加同步优化

    ios::sync_with_stdio(false); cin.tie(0);
  2. 循环优化:减少不必要的循环和条件判断

    • 例如发现冲突后立即跳出多层循环
  3. 变量作用域:将只在循环内使用的变量声明在循环内部

    • 如标记变量f可以在检查每个方案时重新声明
  4. 代码可读性:合理使用注释和空行分隔逻辑块

    • 但注意PTA中注释会增加代码长度

完整代码实现时,建议先写无注释版本通过测试,再添加必要注释。对于竞赛和考试,熟练度比完美注释更重要。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 19:10:10

CaptfEncoder V3:从Rust重构看跨平台安全工具的架构演进

CaptfEncoder V3&#xff1a;从Rust重构看跨平台安全工具的架构演进 【免费下载链接】CaptfEncoder Captfencoder is opensource a rapid cross platform network security tool suite, providing network security related code conversion, classical cryptography, cryptogr…

作者头像 李华
网站建设 2026/4/16 19:08:52

STM32WB55双核开发初体验:当CubeMX遇上蓝牙协议栈,我为何转向研究ESP32?

STM32WB55与ESP32蓝牙开发深度对比&#xff1a;从双核架构到实战选型指南 当我在电子元件商城第一次拿起STM32WB55开发板时&#xff0c;脑海中浮现的是双核处理器与蓝牙协议栈完美协作的画面。作为长期使用STM32系列的老用户&#xff0c;我理所当然地认为这不过是CubeMX生态的又…

作者头像 李华
网站建设 2026/4/16 19:07:56

别再混淆了!用5个实例彻底搞懂Stateflow里的状态动作和转移动作

Stateflow状态机设计&#xff1a;5个实战案例解析状态动作与转移动作的本质区别 在状态机建模领域&#xff0c;Stateflow作为MATLAB/Simulink生态系统中的核心工具&#xff0c;其精确的动作执行机制常常成为初学者进阶路上的绊脚石。许多工程师在首次接触状态动作&#xff08;状…

作者头像 李华
网站建设 2026/4/16 19:06:41

便携式Kali Linux:U盘Live Boot与持久化存储实战指南

1. 为什么需要便携式Kali Linux&#xff1f; 很多网络安全爱好者都面临一个尴尬的处境&#xff1a;既想使用功能强大的Kali Linux进行渗透测试和安全研究&#xff0c;又不想影响自己日常使用的Windows或macOS系统。虚拟机虽然是个解决方案&#xff0c;但存在性能损耗、硬件兼容…

作者头像 李华
网站建设 2026/4/16 19:04:32

3天掌握AutoDock-Vina分子对接:从零到实战的完整指南

3天掌握AutoDock-Vina分子对接&#xff1a;从零到实战的完整指南 【免费下载链接】AutoDock-Vina AutoDock Vina 项目地址: https://gitcode.com/gh_mirrors/au/AutoDock-Vina AutoDock-Vina是当前药物发现领域最流行、最高效的开源分子对接工具&#xff0c;它能够快速预…

作者头像 李华
网站建设 2026/4/16 19:04:31

74LS192芯片的进阶应用:从复位与预置到任意进制转换的实战设计

1. 74LS192芯片基础回顾与核心特性 74LS192作为TTL家族中的明星产品&#xff0c;本质上是一个同步十进制可逆计数器。我第一次接触这个芯片是在大学电子设计课上&#xff0c;当时用它做了一个简易秒表&#xff0c;从此就迷上了它的灵活性。与常见的异步计数器不同&#xff0c;它…

作者头像 李华