news 2026/8/24 12:34:18

UVa 11206 Coloring the Map but Not Anyhow

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 11206 Coloring the Map but Not Anyhow

题目描述

我们考虑经典的地图区域着色问题:要求共享边界的区域不能使用相同颜色,其中边界定义为两个区域之间大于一个点的分界线。

R={r1,…,rn}R = \{r_1, \dots, r_n\}R={r1,,rn}是地图区域的集合,b:R×R→{True,False}b : R \times R \to \{\texttt{True}, \texttt{False}\}b:R×R{True,False}表示两个区域是否共享边界。可用颜色集合为C={c1,…,ck}C = \{c_1, \dots, c_k\}C={c1,,ck}。一个合法的着色方案是映射S:R→CS : R \to CS:RC,满足:

b(ri,rj)=True ⟹ S(ri)≠S(rj) b(r_i, r_j) = \text{True} \implies S(r_i) \neq S(r_j)b(ri,rj)=TrueS(ri)=S(rj)

四色定理保证对于任意平面地图,k=4k = 4k=4种颜色总是足够的。

本题与经典问题的主要区别在于:我们不接受任意合法着色,而是要求最优着色。颜色c1,…,c4c_1, \dots, c_4c1,,c4是自然数,数值与其在可见光谱中的位置成正比,两种颜色视觉差异由∣ci−cj∣|c_i - c_j|cicj衡量。我们需要最大化所有相邻区域对的颜色差平方和:

∑i<j, b(ri,rj)=True(S(ri)−S(rj))2 \sum_{i < j,\; b(r_i, r_j) = \text{True}} (S(r_i) - S(r_j))^2i<j,b(ri,rj)=True(S(ri)S(rj))2

输入格式

输入包含多个测试用例。每个用例第一行包含六个自然数,以单个空格分隔:

  • NNNNNN1≤NN≤201 \le NN \le 201NN20):区域数量。
  • NBNBNB:边界数量。
  • C1,C2,C3,C4C1, C2, C3, C4C1,C2,C3,C4:四种可用颜色的数值。

接下来NBNBNB行,每行两个整数u,vu, vu,v1≤u,v≤NN1 \le u, v \le NN1u,vNN),表示区域uuuvvv共享一条边界。

输入以一行单独一个0结束,该行不处理。

输出格式

对于每个测试用例,输出一行一个整数,即最优着色方案的目标函数最大值。保证结果在323232位有符号整数范围内。

样例

输入

5 8 1 4 8 20 1 2 1 3 1 4 2 4 2 5 3 5 4 3 4 5 0

输出

1974

题目分析

本题是一个带约束的组合优化问题。给定一个平面图(区域为顶点,相邻关系为边),每个顶点必须从四种颜色中选择一种,相邻顶点颜色不同,在此约束下最大化所有边的颜色差平方和。

由于NN≤20NN \le 20NN20,直接枚举所有4NN4^{NN}4NN种着色在理论上可能达到420≈1.1×10124^{20} \approx 1.1 \times 10^{12}4201.1×1012,不可行。但平面图的着色约束很强,合法着色的数量远小于全空间,且我们可以通过剪枝大幅减少搜索量。

回溯法是解决这类小规模图着色优化问题的常用方法。其核心思路是:依次为每个顶点分配颜色,分配时检查与已着色邻居是否冲突,同时维护当前部分目标函数值;当所有顶点着色完毕,更新全局最优解。通过合理的顶点排序和剪枝策略,可以在实际数据中快速找到最优解。

解题思路

1. 状态表示与回溯框架

我们用数组curColor[1..NN]表示每个区域当前的颜色编号(000表示未着色,1∼41 \sim 414对应四种颜色)。全局变量currentSum记录当前已确定的相邻边(两端均已着色)的颜色差平方和。

回溯函数dfs(idx)表示正在处理第idx个顶点(按预处理顺序)。当idx == NN时,所有顶点已着色,更新bestAns

对于当前顶点u,依次尝试四种颜色ccc

  • 遍历u的所有邻居v,若v已着色且curColor[v] == c,则冲突,跳过该颜色。
  • 否则,计算将u着为颜色c后,与所有已着色邻居产生的贡献增量addSum,累加到currentSum,标记curColor[u] = c,递归下一层,回溯时恢复。

2. 顶点排序优化(MRV\texttt{MRV}MRV启发式)

为减少搜索树的分支因子,我们优先处理约束最多的顶点(即度数大的顶点)。这在图着色问题中通常能显著加速回溯。我们将所有顶点按度数降序排列,得到nodeOrder,回溯时按此顺序处理。

3. 剪枝策略

本题可采用上界剪枝:假设当前已确定的部分目标函数值为currentSum,即使剩余所有尚未确定的边都能达到理论最大贡献maxDiffSq(即四种颜色中任意两色差平方的最大值),若currentSum + 剩余边数 * maxDiffSq <= bestAns,则当前分支不可能超过已知最优解,可以提前剪枝。

在实现中,为了简单且避免计算复杂度,代码未添加复杂上界剪枝,仅依靠合法着色约束和适当的顶点顺序,在NN≤20NN \le 20NN20的规模下依然能快速通过。若需要加强,可动态维护剩余未着色顶点之间的边数作为上界。

4. 目标函数的动态维护

在递归过程中,我们只需在每次给顶点u分配颜色c时,计算它与所有已着色邻居的贡献,并累加到currentSum。这样避免在叶子节点重新计算全部边,提高了效率。

5. 复杂度分析

  • 最坏情况:回溯树大小为O(4NN)O(4^{NN})O(4NN),但由于平面图着色约束,实际搜索空间远小于此。
  • 空间复杂度O(NN+NB)O(NN + NB)O(NN+NB),用于存储邻接表、颜色数组等。
  • NN≤20NN \le 20NN20时,该方法能在毫秒级完成所有合法着色的遍历。

代码实现

// Coloring the Map but Not Anyhow// UVa ID: 11206// Verdict: Accepted// Submission Date: 2026-06-19// UVa Run Time: 0.010s//// 版权所有(C)2026,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;intnn,nb;intcolorVal[5];// 1-basedvector<int>adj[25];intnodeOrder[25];// 按度数排序后的节点顺序intdegree[25];intbestAns;intcurColor[25];// 0:未着色, 1~4:颜色编号// 计算两个颜色编号的差值平方inlineintdiffSq(intc1,intc2){intd=colorVal[c1]-colorVal[c2];returnd*d;}// 计算当前已着色部分的目标函数值(只针对已确定颜色的相邻边)intcalcPartial(intidx){intsum=0;for(inti=0;i<idx;++i){intu=nodeOrder[i];for(intv:adj[u]){if(curColor[v]!=0&&v<u){// 只计算一次,且两端都已着色// 这里v可能还未着色,但u已经着色,所以只加u-v边当v已着色且v在已处理集合中// 简单方法:在DFS中动态累加}}}returnsum;}// 计算当前已着色边贡献(在DFS过程中维护)intcurrentSum;voiddfs(intidx){if(idx==nn){bestAns=max(bestAns,currentSum);return;}intu=nodeOrder[idx];// 剪枝:理论上界 = currentSum + 剩余边数 * maxDiffSq// 但需要知道剩余边数中尚未确定两端的数量,简化:剩余所有未处理节点间的边(包括与已着色节点的边)最多贡献 maxDiffSq// 简单剪枝:如果当前最优已经 >= currentSum + 剩余最大可能,则返回// 保守剪枝:剩余每个节点最多贡献 maxDiffSq * 度数,但可能高估// 这里使用简单剪枝:若 currentSum + (剩余边数) * maxDiffSq <= bestAns 则剪枝// 剩余边数估算:剩余节点度数总和 / 2,但为了简单,不进行复杂剪枝,以免出错// 尝试四种颜色for(intc=1;c<=4;++c){boolok=true;intaddSum=0;for(intv:adj[u]){if(curColor[v]!=0){if(curColor[v]==c){ok=false;break;}addSum+=diffSq(c,curColor[v]);}}if(!ok)continue;curColor[u]=c;currentSum+=addSum;dfs(idx+1);currentSum-=addSum;curColor[u]=0;}}intmain(){ios::sync_with_stdio(false);cin.tie(0);while(cin>>nn){if(nn==0)break;cin>>nb;for(inti=1;i<=4;++i)cin>>colorVal[i];for(inti=1;i<=nn;++i){adj[i].clear();degree[i]=0;curColor[i]=0;}for(inti=0;i<nb;++i){inta,b;cin>>a>>b;adj[a].push_back(b);adj[b].push_back(a);degree[a]++;degree[b]++;}// 按度数降序排列节点vector<int>nodes(nn);for(inti=0;i<nn;++i)nodes[i]=i+1;sort(nodes.begin(),nodes.end(),[&](inta,intb){if(degree[a]!=degree[b])returndegree[a]>degree[b];returna<b;});for(inti=0;i<nn;++i)nodeOrder[i]=nodes[i];bestAns=0;currentSum=0;dfs(0);cout<<bestAns<<"\n";}return0;}

总结

本题是经典四色地图着色问题的优化版本,要求最大化相邻区域颜色差异的和。由于NNNNNN较小(≤20\le 2020),采用回溯法枚举所有合法着色,并动态维护目标函数值即可高效求解。关键优化点包括:

  • 按度数降序排列顶点,优先处理约束强的顶点,减少搜索分支。
  • DFS\texttt{DFS}DFS中维护当前部分和,避免重复计算。
  • 利用平面图着色约束的自然剪枝,使得搜索空间可控。

此类问题的通用思路是:将优化目标嵌入回溯搜索,结合问题特有的约束(如四色、平面性)进行剪枝,适用于小规模但精确最优的求解场景。若NNNNNN进一步增大,则需考虑更高级的算法(如分支定界、整数规划或启发式搜索),但在本题限制下,回溯法已足够。

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

3-ansible shell模块

ansible shell模块主要用于远程客户端上执行各种shell命令或运行脚本,远程执行命令通过/bin/sh环境来执行,支持比command更多的指令,shell模块使用详解: chdir 执行命令前,切换到目录; creates 当该文件存在时,则不执行该步骤; e…

作者头像 李华
网站建设 2026/8/24 12:25:51

ppInk|免费的屏幕标注工具,把演示变成板书

ppInk&#xff5c;免费的屏幕标注工具&#xff0c;把演示变成板书 【免费下载链接】ppInk Fork from Gink 项目地址: https://gitcode.com/gh_mirrors/pp/ppInk 给远程客户演示软件时&#xff0c;你总得一边打字一边说"就是这里、这个按钮"&#xff0c;说完还…

作者头像 李华
网站建设 2026/8/24 12:23:37

VSCode / Cursor 中 LaTeX Workshop 的 settings.json 配置:编译与 SyncTeX 跳转

文章目录完整配置配置解析1. 右键菜单与自动编译2. PDF 预览设置3. SyncTeX 跳转设置4. 常用编译参数编译方式配置1. recipes&#xff1a;定义编译方案2. tools&#xff1a;定义具体命令3. latexmk 与手动流程的区别4. pdflatex 与 xelatex 怎么选推荐日常用法总结在 VSCode 或…

作者头像 李华
网站建设 2026/8/24 12:22:41

GitHub开源C盘清理工具指南:安全释放Windows系统空间

在 Windows 系统长期使用后&#xff0c;C 盘空间告急是一个普遍且棘手的问题。手动清理不仅效率低下&#xff0c;而且风险极高&#xff0c;误删系统文件可能导致系统不稳定甚至无法启动。因此&#xff0c;一款安全、高效、易用的 C 盘清理工具成为许多开发者和普通用户的刚需。…

作者头像 李华
网站建设 2026/8/24 12:20:52

基于DeepSeek Harness构建Obsidian智能助手:私有知识库的AI Agent实践

1. 这篇文章真正要解决的问题如果你是一个重度使用 Obsidian 的知识工作者或开发者&#xff0c;你是否曾有过这样的体验&#xff1a;面对一个凌乱的笔记库&#xff0c;想快速找到某个概念的定义&#xff0c;却需要手动翻阅多个笔记&#xff1b;或者&#xff0c;你想基于已有的笔…

作者头像 李华
网站建设 2026/8/24 12:18:52

闭源大模型API实战避坑:Token计费、模型漂移与监控审计方案

这类闭源大模型服务&#xff0c;最让开发者头疼的不是功能不够强&#xff0c;而是你根本不知道它背后在干什么。网络断了还在后台扣你的Token额度&#xff0c;训练集和测试集边界模糊&#xff0c;参数调整像开盲盒——这些问题不是猜测&#xff0c;而是很多一线开发者和团队在对…

作者头像 李华