当前位置: 首页 > news >正文

UVa 1327 King‘s Quest

题目描述

国王有NNN个儿子,还有NNN个美丽的女孩。每个王子都有自己喜欢的女孩列表(可能喜欢多个女孩)。巫师已经给出了一个初始的完美匹配方案,即每个王子都匹配到了一个他喜欢的女孩,且每个女孩只匹配一个王子。

现在国王要求:对于每个王子,找出所有他可以娶的女孩,使得在娶了这个女孩之后,剩下的王子仍然能够全部匹配到喜欢的女孩(即仍然存在完美匹配)。

输入格式

  • 第一行:NNN1≤N≤20001 \leq N \leq 20001N2000),表示王子的数量
  • 接下来NNN行:每行先是一个整数KiK_iKi,表示该王子喜欢的女孩数量,接着是KiK_iKi个不同的整数(111NNN),表示喜欢的女孩编号
  • 最后一行:NNN个不同的整数,表示巫师给出的初始匹配方案(第iii个数表示王子iii初始匹配的女孩)

输出格式

对于每个王子,输出一行:

  • 首先是一个整数LiL_iLi,表示该王子可以选择的女孩数量
  • 接着是LiL_iLi个整数,表示这些女孩的编号(顺序任意)

题目分析

问题本质

这是一个二分图匹配的扩展问题。我们需要在保持全局完美匹配存在的前提下,找出每个王子可以选择的所有女孩。

关键观察

  1. 初始匹配:巫师给出的匹配是一个合法的完美匹配
  2. 可交换性:如果一个王子可以换到另一个女孩,同时保持全局匹配存在,那么这两个匹配关系必须在某种意义上是"可交换"的
  3. 图论建模:可以将问题转化为有向图中的强连通分量(SCC\texttt{SCC}SCC)问题

算法思路

1. 构建有向图

我们将王子和女孩都看作图中的节点:

  • 节点000N−1N-1N1表示王子
  • 节点NNN2N−12N-12N1表示女孩(女孩ggg对应节点N+g−1N + g - 1N+g1

构建有向边的规则:

  • 对于王子iii喜欢的每个女孩ggg
    • 如果ggg不是他的初始匹配女孩,则添加边i→(N+g−1)i \rightarrow (N + g - 1)i(N+g1)
  • 对于每个女孩ggg(在初始匹配中匹配给王子iii):
    • 添加边(N+g−1)→i(N + g - 1) \rightarrow i(N+g1)i
2. 强连通分量(SCC\texttt{SCC}SCC)的意义

在这个有向图中,如果王子iii和女孩jjj在同一个强连通分量中,那么:

  • 王子iii可以选择女孩jjj,同时通过分量内的边重新调整匹配,使得所有王子仍然有匹配
3. 求解步骤
  1. 读入数据并构建有向图
  2. 使用Tarjan\texttt{Tarjan}Tarjan算法求强连通分量
  3. 对于每个王子iii
    • 初始匹配的女孩一定可以选
    • 其他喜欢的女孩ggg可以选当且仅当王子iii和女孩ggg在同一个SCC\texttt{SCC}SCC

算法正确性证明

  • 初始匹配的女孩总是可选的(不改变匹配)
  • 如果王子iii和女孩jjj在同一个SCC\texttt{SCC}SCC中,那么存在从iiijjj和从jjjiii的路径
  • 这意味着可以通过SCC\texttt{SCC}SCC内的环来重新分配匹配,使得王子iii匹配女孩jjj,同时其他王子仍然有匹配

复杂度分析

  • 节点数:2N2N2N(最多400040004000
  • 边数:∑Ki≤200000\sum K_i \leq 200000Ki200000
  • Tarjan 算法复杂度:O(N+E)O(N + E)O(N+E),完全可行

代码实现

// King's Quest// UVa ID: 1327// Verdict: Accepted// Submission Date: 2025-10-16// UVa Run Time: 0.330s//// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;constintMAXN=4005;// 最多 2N 个节点vector<int>G[MAXN];// 邻接表intidx[MAXN],low[MAXN],scc_id[MAXN],scc_cnt,ts;// Tarjan 算法相关数组intstk[MAXN],top;// 栈boolin_stk[MAXN];// 标记节点是否在栈中// Tarjan 算法求强连通分量voidtarjan(intu){idx[u]=low[u]=++ts;stk[top++]=u;in_stk[u]=true;for(intv:G[u]){if(!idx[v]){tarjan(v);low[u]=min(low[u],low[v]);}elseif(in_stk[v]){low[u]=min(low[u],idx[v]);}}if(low[u]==idx[u]){intx;do{x=stk[--top];in_stk[x]=false;scc_id[x]=scc_cnt;}while(x!=u);scc_cnt++;}}intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intN;while(cin>>N){// 初始化图和相关数组for(inti=0;i<2*N;i++){G[i].clear();idx[i]=low[i]=scc_id[i]=0;in_stk[i]=false;}scc_cnt=ts=top=0;// 读入每个王子的喜好vector<vector<int>>like(N);for(inti=0;i<N;i++){intk;cin>>k;like[i].resize(k);for(intj=0;j<k;j++){cin>>like[i][j];}}// 读入初始匹配vector<int>match(N);for(inti=0;i<N;i++){cin>>match[i];}// 构建有向图for(inti=0;i<N;i++){for(intg:like[i]){if(g==match[i])continue;// 初始匹配不建边// 王子 i -> 女孩 gG[i].push_back(N+g-1);}}for(inti=0;i<N;i++){// 女孩 match[i] -> 王子 i(初始匹配的反向边)G[N+match[i]-1].push_back(i);}// 求强连通分量for(inti=0;i<2*N;i++){if(!idx[i])tarjan(i);}// 输出答案for(inti=0;i<N;i++){vector<int>ans;for(intg:like[i]){// 可以选的女孩:初始匹配的女孩 或 在同一个 SCC 中的女孩if(g==match[i]||scc_id[i]==scc_id[N+g-1]){ans.push_back(g);}}sort(ans.begin(),ans.end());cout<<ans.size();for(intg:ans){cout<<" "<<g;}cout<<"\n";}}return0;}

总结

本题通过将二分图匹配问题转化为有向图的强连通分量问题,巧妙地解决了"在保持全局匹配存在的前提下找出所有可选匹配"的问题。这种SCC\texttt{SCC}SCC的建模方法在图论和匹配问题中有着广泛的应用,是解决此类问题的经典技巧。

关键点在于理解:

  1. 初始匹配提供了图的骨架
  2. 额外的喜欢关系构成了潜在的可交换路径
  3. 强连通分量内的节点可以自由交换而不破坏匹配的完整性

这种方法的时间复杂度为O(N+E)O(N + E)O(N+E),能够高效处理题目给出的数据规模。

http://www.jsqmd.com/news/749305/

相关文章:

  • Python跨端开发卡顿元凶曝光:4步精准定位渲染延迟,iOS/Android/Windows三端同步提速60%
  • LLM驱动的智能测试自动化框架设计与实践
  • 国产化开发环境搭建实录:在银河麒麟Kylin V10上,用SVN管理Qt项目源码的完整流程
  • 数据合规新范式:Redpanda Connect GDPR全链路保护方案
  • OpenSpeedy:终极游戏加速神器完整指南与使用技巧
  • 基于安卓的传感器数据采集与分析平台毕业设计源码
  • CogVideoX-2b技术拆解:Web界面如何调用本地模型服务
  • GLM-4.7-Flash实战教程:基于该模型构建私有化知识库RAG应用全流程
  • 2026最权威的五大AI科研方案推荐榜单
  • OpenClaw:基于配置驱动的Terraform Provider快速开发框架
  • EagleEye容器化升级:Kubernetes集群部署+HPA自动扩缩容实战
  • 2026年3月市面上可靠的洁净手术室厂家推荐,洁净手术室/医用气体/厂房净化/手术室净化/无菌手术室,洁净手术室工程推荐 - 品牌推荐师
  • SunnyUI多页面框架实战:快速构建企业级WinForm应用
  • ReactPress:用现代前端工具链开发WordPress主题的实践指南
  • 别再被‘Rendering has stopped’卡住!手把手教你用CDN和本地两种方式在VS Code里跑通Cesium 1.82
  • 终极指南:如何在Vim中使用syntastic实现Kotlin语法检查
  • dufs:一个命令,把文件夹变成网盘
  • 终极指南:如何用Appleseed开源渲染引擎创建逼真图像
  • VS Codium深度体验报告:除了没有遥测,它和VS Code到底还有啥不一样?(附性能实测)
  • AI Agent生产部署:缰绳工程实战指南与Awesome-Harness-Engineering资源解析
  • 植入式芯片长期生物相容性技术研究报告(世毫九实验室原创研究)
  • Gemma-4-26B-A4B-it-GGUF保姆级教程:Supervisor服务管理命令速查与故障修复
  • 2026庭院烤漆门户外适配技术解析与合规选材指南:原木色烤漆门、同色门墙柜、复合烤漆门、实木门墙柜、室内烤漆门选择指南 - 优质品牌商家
  • Arm Neoverse V1架构解析与电源管理设计
  • Awesome Bootstrap Checkbox圆角与禁用状态处理指南
  • egergergeeert开源模型教程:如何从零部署并自定义FLUX.1文生图服务
  • FPGA验证技术:静态时序分析与动态仿真实战
  • 基于Go WebSocket库murmur构建高性能实时通信服务实战
  • 告别训练慢、精度低:手把手教你用NanoDet-Plus的AGM模块加速模型收敛
  • 神经网络表示相似性:亚里士多德假设与校准方法