[蓝桥杯]模型染色
模型染色
题目描述
在电影《超能陆战队》中,小宏可以使用他的微型机器人组合成各种各样的形状。
现在他用他的微型机器人拼成了一个大玩具给小朋友们玩。为了更加美观,他决定给玩具染色。
小宏的玩具由 nn 个球型的端点和 mm 段连接这些端点之间的边组成。下图给出了一个由 5 个球型端点和 4 条边组成的玩具,看上去很像一个分子的球棍模型。
由于小宏的微型机器人很灵活,这些球型端点可以在空间中任意移动,同时连接相邻两个球型端点的边可以任意的伸缩,这样一个玩具可以变换出不同的形状。在变换的过程中,边不会增加,也不会减少。
小宏想给他的玩具染上不超过 kk 种颜色,这样玩具看上去会不一样。如果通过变换可以使得玩具变成完全相同的颜色模式,则认为是本质相同的染色。现在小宏想知道,可能有多少种本质不同的染色。
输入描述
输入的第一行包含三个整数 n,m,kn,m,k,分别表示小宏的玩具上的端点数、边数和小宏可能使用的颜色数。端点从 1 到 nn编号。
接下来 mm 行每行两个整数 a,ba,b,表示第 aa 个端点和第 bb 个端点之间有一条边。输入保证不会出现两条相同的边。
其中,1≤n≤10,1≤m≤45,1≤k≤301≤n≤10,1≤m≤45,1≤k≤30。
输出描述
输出一行,表示本质不同的染色的方案数。由于方案数可能很多,请输入方案数除 10007 的余数。
输入输出样例
示例
输入
3 2 2
1 2
3 2
输出
6
样例说明
令 (a,b,c)(a,b,c) 表示第一个端点染成 aa,第二个端点染成 bb,第三个端点染成 cc,则下面 6 种本质不同的染色:(1,1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2), (2, 1, 2), (2, 2, 2)。
而(2, 1, 1)与(1, 1, 2)是本质相同的,(2, 2, 1)与(1, 2, 2)是本质相同的。
运行限制
- 最大运行时间:5s
- 最大运行内存: 512M
总通过次数: 118 | 总提交次数: 184 | 通过率: 64.1%
难度: 困难 标签: 2015, 国赛, 搜索
算法思路:基于Burnside引理的图染色计数
本问题要求计算在图的连续变形(自同构)下本质不同的染色方案数。核心思路是使用Burnside引理:本质不同的染色方案数等于自同构群作用下所有置换的不动点数的平均值。具体步骤如下:
- 问题转化:将本质不同的染色方案转化为在图的顶点自同构群作用下的轨道数。
- Burnside引理:本质不同的染色方案数公式为:
ans=∣G∣1∑g∈Gkc(g)mod10007
其中 ∣G∣ 是自同构群大小,c(g) 是置换 g 的轮换个数,k 是颜色数。 - 自同构判定:置换 g 是自同构当且仅当对原图的每条边 (u,v),置换后 (g(u),g(v)) 仍是图中的边。
- 轮换分解:对每个自同构置换,分解轮换并统计轮换个数 c(g)。
算法步骤
- 输入处理:读取顶点数 n、边数 m、颜色数 k,构建邻接矩阵。
- 置换生成:枚举 0 到 n−1 的所有排列(使用
next_permutation
)。 - 自同构检查:对每个置换,检查原图所有边置换后是否仍是图中的边。
- 轮换分解:对自同构置换进行轮换分解,统计轮换个数 c(g)。
- 不动点计算:计算 kc(g)mod10007 并累加。
- 结果计算:累加和乘以自同构群大小的逆元(模 10007)。
代码实现(C++)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;const int MOD = 10007;// 快速幂取模
int mod_pow(int base, int exp, int mod) {int res = 1;base %= mod;while (exp) {if (exp & 1) res = (res * base) % mod;base = (base * base) % mod;exp >>= 1;}return res;
}int main() {int n, m, k;cin >> n >> m >> k;// 邻接矩阵和边列表初始化vector<vector<int>> adj(n, vector<int>(n, 0));vector<pair<int, int>> edges;// 输入边并构建邻接矩阵for (int i = 0; i < m; i++) {int a, b;cin >> a >> b;a--; b--; // 转换为0-indexadj[a][b] = adj[b][a] = 1;if (a > b) swap(a, b);edges.push_back({a, b});}// 生成初始置换 [0, 1, ..., n-1]vector<int> perm(n);for (int i = 0; i < n; i++) perm[i] = i;int group_size = 0; // 自同构群大小int sum_terms = 0; // 累加项do {bool is_automorphism = true;// 检查每条边置换后是否仍存在for (auto &e : edges) {int u = e.first, v = e.second;if (!adj[perm[u]][perm[v]]) {is_automorphism = false;break;}}if (is_automorphism) {group_size++;// 轮换分解vector<bool> visited(n, false);int cycle_count = 0;for (int i = 0; i < n; i++) {if (!visited[i]) {cycle_count++;int cur = i;while (!visited[cur]) {visited[cur] = true;cur = perm[cur];}}}// 累加 k^{cycle_count} mod MODsum_terms = (sum_terms + mod_pow(k, cycle_count, MOD)) % MOD;}} while (next_permutation(perm.begin(), perm.end()));// 计算逆元:inv = group_size^{MOD-2} mod MODint inv = mod_pow(group_size, MOD-2, MOD);int ans = sum_terms * inv % MOD;cout << ans << endl;return 0;
}
代码解析
- 输入处理(L19-27):
- 读取 n,m,k,初始化邻接矩阵
adj
和边列表edges
。 - 将输入的边转换为0-index存储,并标记邻接矩阵。
- 读取 n,m,k,初始化邻接矩阵
- 置换生成(L30-33):
- 初始化置换数组
perm
为 [0,1,…,n−1]。 - 使用
next_permutation
遍历所有排列。
- 初始化置换数组
- 自同构检查(L36-44):
- 对每条边 (u,v),检查置换后 (perm[u],perm[v]) 是否仍是图中的边。
- 若所有边检查通过,则判定为自同构。
- 轮换分解(L47-58):
- 使用
visited
数组标记访问过的顶点。 - 对每个未访问顶点进行DFS遍历,统计轮换个数
cycle_count
。
- 使用
- 不动点累加(L60):
- 计算 k^{\text{cycle_count}} \mod 10007 并累加到
sum_terms
。
- 计算 k^{\text{cycle_count}} \mod 10007 并累加到
- 结果计算(L64-66):
- 计算自同构群大小的逆元
inv
(费马小定理)。 - 输出 sum_terms×invmod10007。
- 计算自同构群大小的逆元
实例验证
输入:3 2 2
,边 (1,2)
和 (3,2)
自同构群:
- 单位置换:
[0,1,2]
→ 轮换数=3 → 23=8 - 置换
[2,1,0]
:轮换数=2 → 22=4 - 总和 8+4=12,群大小 2 → 12/2=6 ✓
注意事项
- 顶点索引转换:输入顶点从1开始,需转换为0-index处理。
- 逆元计算:模数 10007 是素数,使用费马小定理求逆元。
- 性能边界:n=10 时置换数 10!≈3.6×106,边数 m≤45,总操作数约 1.6×108,在5秒内可完成。
- 轮换分解:使用DFS避免重复计数。
多方位测试点
测试类型 | 输入样例 | 预期输出 | 验证要点 |
---|---|---|---|
最小图(n=1) | 1 0 3 | 3 | 单点边界 |
无自同构图 | 3 1 2 1 2 | 4 | 单位置换唯一性 |
完全图(K4) | 4 6 3 | 15 | 对称性处理 |
星形图 | 4 3 2 1 2 1 3 1 4 | 6 | 叶子交换对称性 |
全边图(m=45) | 10 45 5 | 1 | 完全图自同构群大小 10! |
优化建议
- 剪枝优化:
// 在生成排列时提前终止无效置换 if (!is_automorphism) continue;
- 并行计算(OpenMP):
#pragma omp parallel for reduction(+:sum_terms, group_size) for (int i = 0; i < total_perm; i++) {// 并行处理置换 }
- 自同构群加速:
- 使用nauty等图同构库直接生成自同构群,避免全排列枚举。
- 缓存优化:
- 预计算幂结果:kc 中 c≤n,可预先计算 k1 到 kn 的模值。
相关文章:

[蓝桥杯]模型染色
模型染色 题目描述 在电影《超能陆战队》中,小宏可以使用他的微型机器人组合成各种各样的形状。 现在他用他的微型机器人拼成了一个大玩具给小朋友们玩。为了更加美观,他决定给玩具染色。 小宏的玩具由 nn 个球型的端点和 mm 段连接这些端点之间的边…...
力扣上C语言编程题
一. 简介 本文简单记录一下力扣上 C语言编程题。作为自己做题笔记。 二. 力扣上 C 语言编程题 1. 从数组中找到两个元素之和,等于一个 target目标值 具体题目说明:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为…...

卡西欧模拟器:Windows端功能强大的计算器
引言 大家还记得初中高中时期用的计算器吗?今天给大家分享的就是一款windows端的卡西欧计算器。 软件介绍 大家好,我是逍遥小欢。 CASIO fx-9860G是一款功能强大的图形计算器,适用于数学、科学和工程计算。以下是其主要功能和特点的详细介…...
鸿蒙OSUniApp结合机器学习打造智能图像分类应用:HarmonyOS实践指南#三方框架 #Uniapp
UniApp结合机器学习打造智能图像分类应用:HarmonyOS实践指南 引言 在移动应用开发领域,图像分类是一个既经典又充满挑战的任务。随着机器学习技术的发展,我们现在可以在移动端实现高效的图像分类功能。本文将详细介绍如何使用UniApp结合Ten…...

机器学习基础(三) 逻辑回归
目录 逻辑回归的概念核心思想 Sigmoid 函数 逻辑回归的原理和底层优化手段伯努利分布最大似然估计 Maximum Likelihood Estimation (MLE)伯努利分布的似然函数交叉熵损失函数(Cross-Entropy Loss),也称为 对数损失&…...
系统调试——ADB 工具
ADB 工具 1.1 概述 ADB(Android Debug Bridge) 是 Android SDK 里的一个工具, 用这个工具可以操作管理Android 模拟器或真实的 Android 设备。 主要功能有: 运行设备的 shell(命令行)管理模拟器或设备的端…...

Qwen-3 微调实战:用 Python 和 Unsloth 打造专属 AI 模型
虽然大家都忙着在 DeepSeek 上构建应用,但那些聪明的开发者们却悄悄发现了 Qwen-3 的微调功能,这可是一个隐藏的宝藏,能把通用型 AI 变成你的专属数字专家。 通过这篇文章,你将学到如何针对特定用途微调最新的 Qwen-3 模型。无论…...

微软Build 2025:Copilot Studio升级,解锁多智能体协作未来
微软Build 2025大会圆满落幕,作为年度科技盛会,它一直是开发与AI技术突破性创新的重要展示平台。对于工程师、创作者和领域专家来说,这是了解微软生态未来动向的关键时刻。今年,Microsoft Copilot Studio推出了一系列新功能&#…...

设计模式——系统数据建模设计
摘要 本文主要介绍了UML在软件系统分析和设计中的应用,详细阐述了六大类关系(泛化、实现、依赖、关联、聚合、组合)及其在UML类图中的表示方法,并通过具体例子说明了这些关系在实际编程中的应用。同时,文章还概述了UM…...

解决docker运行zentao 报错:ln: failed to create symbolic link ‘/opt/zbox/tmp/mysq
1 背景描述 禅道使用docker部署运行过一段,服务正常。 后因服务器断电重启,禅道服务也随docker一起启动,但是服务却无法访问。如下如: 2 查看日志,定位原因 查看禅道日志: # docker logs zentao容器di…...
Spring Boot MVC自动配置与Web应用开发详解
Spring Boot MVC自动配置机制 Spring Boot通过自动配置功能为MVC应用提供了开箱即用的默认配置,开发者无需手动配置即可获得完整的Web支持。以下是核心功能的实现原理: 静态资源支持 默认情况下,Spring Boot会自动从以下classpath目录提供…...

OA工程自动化办公系统 – 免费Java源码
概述 功能完备的OA工程自动化办公系统Java源码,采用主流技术栈开发,无论是学习SpringBoot框架还是开发企业级应用,都是不可多得的优质资源。 主要内容 技术架构 后端技术栈: 核心框架:SpringBoot 2.xORM框…...

Apache IoTDB V2.0.3 发布|新增元数据导入导出脚本适配表模型功能
Release Announcement Version 2.0.3 Apache IoTDB V2.0.3 已经发布! V2.0.3 作为树表双模型正式版本,主要新增元数据导入导出脚本适配表模型、Spark 生态集成(表模型)、AINode 返回结果新增时间戳,表模型新增部分聚…...

某校体育场馆结构自动化监测
1. 项目简介 某小学学校成立于2020年,是一所公办小学,以高起点定位为该区优质教育新增长极,依托当地学院及教师进修学院附属小学资源,注重学生综合素质培养,近年来,该小学聚焦“五育” 领域,不…...
MySQL 9.0 相较于 MySQL 8.0 引入了多项重要改进和新特性
MySQL 9.0 相较于 MySQL 8.0 引入了多项重要改进和新特性,以下是两者的主要区别及其详细说明: 1. 认证机制 MySQL 8.0 支持 mysql_native_password 和 caching_sha2_password 认证插件。默认使用 caching_sha2_password,但未完全移除 mysql_native_password。MySQL 9.0 完全…...

Android 3D球形水平圆形旋转,旋转动态更换图片
看效果图 1、事件监听类 OnItemClickListener:3D旋转视图项点击监听器接口 public interface OnItemClickListener {/*** 当旋转视图中的项被点击时调用** param view 被点击的视图对象* param position 被点击项在旋转视图中的位置索引(从0开始&a…...

数据结构与算法学习笔记(Acwing 提高课)----动态规划·树形DP
数据结构与算法学习笔记----动态规划树形DP author: 明月清了个风 first publish time: 2025.6.4 ps⭐️树形动态规划(树形DP)是处理树结构问题的一种动态规划方法,特征也很明显,会有一个树形结构,其实是DFS的优化。…...
FTP 和 SFTP 介绍及 C/C++ 实现分析
1. FTP 协议概述 FTP(File Transfer Protocol)是一种用于在网络上进行文件传输的标准协议,诞生于 1971 年,是互联网上最早的应用层协议之一。它基于客户端 - 服务器模型,使用 TCP 作为传输层协议,默认通过 …...

leetcode hot100刷题日记——36.最长连续序列
解答: 实际上在哈希表中存储不重复的数字。 然后遍历哈希表,找间隔,更新最大间隔。 class Solution { public:int longestConsecutive(vector<int>& nums) {unordered_set<int>hash;for(int num:nums){hash.insert(num);}in…...

CentOS7关闭防火墙、Linux开启关闭防火墙
文章目录 一、firewalld开启、关闭防火墙1、查看防火墙状态 一、firewalld开启、关闭防火墙 以下命令在linux系统CentOS7中操作开启关闭防火墙 # 查询防火墙状态 systemctl status firewalld.service # 开启防火墙 systemctl start firewalld.service # 开机自启动防火墙 syste…...

PyTorch——搭建小实战和Sequential的使用(7)
import torch from torch import nn from torch.nn import Conv2d, MaxPool2d, Flatten, Linearclass TY(nn.Module):def __init__(self):"""初始化TY卷积神经网络模型模型结构:3层卷积池化,2层全连接设计目标:处理32x32像素的…...
基于大模型的腔隙性脑梗塞风险预测及治疗方案研究
目录 一、引言 1.1 研究背景与意义 1.2 研究目的与方法 1.3 国内外研究现状 二、腔隙性脑梗塞概述 2.1 定义与分类 2.2 发病机制与病理生理过程 2.3 临床表现与诊断方法 三、大模型技术原理与应用现状 3.1 基本概念与技术架构 3.2 在医疗领域的应用案例与优势 3.3 …...

Python 开发效率秘籍:PyCharm、VS Code 与 Anaconda 配置与实战全解
目录 一、IDE(集成开发环境)是什么?二、Python IDE有哪些,哪款适合初学者?三、Visual Studio Code下载和安装教程3.1 VS Code下载和安装3.2 VS Code运行Python程序 四、PyCharm下载和安装教程4.1 PyCharm下载4.2 PyCharm安装4.3 运行PyCharm4.4 创建工程…...
[C]C语言日志系统宏技巧解析
代码解释:日志标签字符串化宏 这段代码定义了一个名为 _LOG_TAG 的宏,用于将 LOG_TAG_CONST 转换为字符串形式。这在日志系统中很常见,用于为不同模块添加标识前缀。 宏结构分析 #define _LOG_TAG STR(LOG_TAG_CON…...
自动驾驶系统研发系列—激光雷达感知延迟:自动驾驶安全的隐形隐患?
🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中一起航行,共同成长,探索技术的无限可能。 🚀 探索专栏:学…...
内网应用如何实现外网访问?无公网IP本地端口网址服务提供互联网连接
一、应用程序外网访问遇到的问题 在现实的工作场景中,在公司内网的服务器上有很多的应用系统,这些系统只能局限于在公司内部使用,而在外网却无法使用。 二、外网访问内网应用常见的解决方案 如何在外网使用这些系统呢?下面简单…...

大话软工笔记—组合要素1之要素
1. 要素来源 对象是要素的来源,要素是从对象分解而来的。可将对象分为优化类和非优化类,如下图所示。 对象分类图 2. 要素的概念 2.1 要素的定义 要素,是构成事物必不可少的因素,要素的集合体构成了对象。 2.2 要素的内容 要…...
oracle从表B更新拼接字段到表A
oracle中表A怎么从表B中追加相对应的编码到表A字段里, 在Oracle数据库中,如果你想从表B中获取数据并更新到表A的某个字段里,可以使用UPDATE语句结合子查询来实现。假设表A有一个字段叫做code,你希望根据某个键(比如id&…...

平台化 LIMS 系统架构 跨行业协同与资源共享的实现路径
在科技快速发展的今天,质检行业正面临着效率、合规和数据安全的多重挑战。新一代质检 LIMS 系统以智能化与平台化为核心,为实验室管理提供了全新的解决方案。 一、智能化:从数据采集到分析的全流程升级 传统质检流程中,人工数据录…...

RedisTemplate查询不到redis中的数据问题(序列化)
RedisTemplate查询不到redis中的数据问题(序列化) 一.问题描述 存入Redis中的值取出来却为null,问题根本原因就是RedisTemplate和StringRedisTemplate的序列化问题、代码示例: SpringBootTest class Redis02SpringbootApplicationTests {Autowiredprivate RedisTe…...