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

LG15645 [ICPC 2022 Tehran R] Network Topology in Hezardastan 题解

LG15645 [ICPC 2022 Tehran R] Network Topology in Hezardastan 题解

\(m\) 个终端,\(n\) 个服务器(\(m\le n\))。\(m\times n\) 的 0/1 矩阵表示连接终端与服务器是否连接。称大小为 \(m\) 的服务器子集 \(S\)可管理的,则存在双射使每个终端连到不同服务器(即服务器子集可以终端完美匹配)。若所有大小为 \(m\) 的子集均可管理,输出 1;否则输出 0 及任意一个不可管理的大小为 \(m\) 的子集(服务器编号)。\(m\leq 150,n\leq 400,m\leq n\)

是一个二分图,容易想到 Hall 定理,设 \(T\) 为一个终端的非空子集\(N(T)\) 为所有与 \(T\) 相邻顶点集合,则

\[\forall T,|N(T)\cap S|\geq |T| \]

\(|N(T)\cap S|\)\(S\) 中与 \(T\) 相连的集合大小(即节点个数),要最小化这个值才能使条件不满足。要最小化的话,需要 \(S\) 选取时尽量不包含 \(N(T)\) 中的节点。记服务器集合全集为 \(U\)

  • \(|U\setminus N(T)|=n-|N(T)|\geq m\),则取 \(S\subseteq U\setminus N(T)\) 即可构造出 \(|N(T)\cap S|=0\),说明存在不可管理服务器子集。

  • 否则 \(S\) 包含 \(|U\setminus N(T)|=n-|N(T)|\) 个不属于 \(N(T)\) 的元素,\(|N(T)\cap S|=m-(n-|N(T)|)\geq |T|\)

综上可以得到子集均可管理的充要条件

\[\forall T, |N(T)|-|T|\geq n-m \]

\(F(T)=|N(T)|-|T|\),现在要求 \(F(T)\) 的最小值以及与 \(n-m\) 的关系。

如果构造这样一个网络流模型

源点 \(s\) 向每个终端(左侧点)连一条流量为 \(1\) 的边,每个终端向相连的服务器(右侧点)连一条流量为 \(+\infty\) 的边,每个服务器向汇点连一条流量为 \(1\) 的边。

则求这个模型的最小割,中间终端与服务器的边不会属于最小割,将不属于左侧最小割的点视作 \(T\),则右侧需要属于最小割的点为 \(N(T)\),最小割为 \(|N(T)|+(m-|T|)=F(T)+m\),则需要判断最小割与 \(n\) 的关系。

最小割等于最大流,这个结论应该不必多说了

由于我们没要求 \(T\) 非空,除非原图的匹配就小于 \(m\)(此时不管怎么选都不会有可管理服务器),那么最小割就会等于 \(m\),对应 \(T\) 为空集,左侧边全部被割掉的情况。现在还需要求非空 \(T\) 的最小割。

这样很好做,每次给一条源点 \(s\) 向终端(左侧点)的边流量改为 \(\infty\),则这条边就不可能属于最小割,那么 \(T\) 中必须包含这个点,此时求得的最小割对应的集合 \(T\) 就是非空的。

如果其中一个最小割的值 \(<n\),那么 \(F(T)=最小割-m<n-m\),就存在不可管理的服务器子集。现在构造出这个子集,左侧不属于最小割的点集即为 \(T\),计算出 \(T\) 的邻集 \(N(T)\),优先选择 \(U\setminus N(T)\) 中的点,接着选择 \(N(T)\) 中的点直到 \(m\) 个,根据一开始的证明,选择的 \(N(T)\) 中的点的个数是小于 \(|T|\) 的,这也意味着单独 \(T\) 这个终端子集就一定无法与服务器子集 \(S\) 完美匹配,于是整个终端集合也无法与服务器子集 \(S\) 完美匹配,找到了一组解。

Dinic 算法求二分图匹配单次复杂度 \(O(E\sqrt V)=O(nm\sqrt{n+m})\),总复杂度 \(O(m^2n\sqrt{n+m})\),可以通过此题。

#include <bits/stdc++.h>using namespace std;typedef long long ll;
typedef pair<int,int>ttfa;
const int N=500005;
const int INF=0x3f3f3f3f;
const ll llINF=0x3f3f3f3f3f3f3f3f;struct net_flow{struct chainstar{int nxt,v;ll w;}edge[N];int head[N],now[N],ecnt=1;int S,T,n,dep[N];inline void init(int SS,int TT,int nn){S=SS,T=TT,n=nn,ecnt=1;for(int i=0;i<=n;++i)head[i]=now[i]=0;}inline void addline(int u,int v,ll w){edge[++ecnt].nxt=head[u];head[u]=ecnt;edge[ecnt].v=v;edge[ecnt].w=w;}inline int addedge(int u,int v,ll w){addline(u,v,w);addline(v,u,0ll);return ecnt-1;}queue<int>q;inline bool bfs(){for(int i=0;i<=n;++i)dep[i]=0;dep[S]=1;q.push(S);while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;if(edge[i].w>0&&!dep[v]){dep[v]=dep[u]+1;q.push(v);}}}return dep[T];}ll dfs(int u,ll f){if(u==T)return f;ll tmp=0;for(int i=now[u];i&&f;i=edge[i].nxt,now[u]=i){int v=edge[i].v;if(edge[i].w>0&&dep[v]==dep[u]+1){ll ttf=dfs(v,min(f,edge[i].w));if(ttf==0)dep[v]=n+2;edge[i].w-=ttf;edge[i^1].w+=ttf;tmp+=ttf;f-=ttf;}}return tmp;}ll dinic(){ll sum=0ll;while(bfs()){for(int i=0;i<=n;++i)now[i]=head[i];while(ll tmp=dfs(S,llINF))sum+=tmp;}return sum;}
}flow;int n,m;
int a[155][405];void buildmap(){flow.init(n+m+1,n+m+2,n+m+2);for(int i=1;i<=m;++i){flow.addedge(flow.S,i,1);}for(int i=1;i<=n;++i){flow.addedge(m+i,flow.T,1);}for(int i=1;i<=m;++i){for(int j=1;j<=n;++j){if(a[i][j])flow.addedge(i,j+m,2*n);}}
}int main(){scanf("%d%d",&m,&n);for(int i=1;i<=m;++i){for(int j=1;j<=n;++j){scanf("%d",&a[i][j]);}}buildmap();int sum=flow.dinic();if(sum<m){puts("0");for(int i=1;i<=m;++i){if(i!=1)printf(" ");printf("%d",i);}puts("");return 0;}for(int i=1;i<=m;++i){buildmap();flow.edge[i*2].w=2*n;sum=flow.dinic();if(sum<n){vector<int>lis,tag(n+1,0);for(int j=1;j<=m;++j){if(flow.edge[j*2].w>0){for(int k=1;k<=n;++k){if(a[j][k])tag[k]=1;}}}for(int k=1;k<=n;++k){if(!tag[k])lis.push_back(k);}for(int k=1;k<=n;++k){if(tag[k])lis.push_back(k);}while((int)lis.size()>m)lis.pop_back();sort(lis.begin(),lis.end());puts("0");for(int j=0;j<m;++j){if(j)printf(" ");printf("%d",lis[j]);}puts("");return 0;}}puts("1");return 0;
}

如果证明有错误请多多指正。

另外这个题如果你的写法和原始出题人不一样,大概是只能在洛谷上通过的,这里给洛谷点个赞。其他平台上的 spj 都有问题(包括但不限于答案集合不排序不行,答案集合是正确的仍判错)。

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

相关文章:

  • 2026现阶段湖南抗倍特板工厂选择指南:深度剖析恒筑邦建材的综合实力 - 2026年企业推荐榜
  • 微环谐振器非线性效应:从克尔效应到光学频率梳的工程实践
  • BiliBiliToolPro:解放双手的B站自动化神器,让你的账号管理从未如此轻松
  • 保姆级教程:用Materials Studio的Forcite模块搞定氢在钨表面的吸附模拟(附避坑指南)
  • 最新彩虹云商城重构版 虚拟商城 在线下单 自动发货
  • BUG自愈实测:OpenAI Codex CLI 自动修复逻辑漏洞的4类典型场景与3步接入方案
  • 2026年当下,上海两翼自动旋转门直销工厂如何选?深度剖析核孚门窗 - 2026年企业推荐榜
  • 智能网络优化工具:一键解决GitHub访问慢的终极方案
  • 10分钟搞定黑苹果:OpCore-Simplify如何将复杂配置变得像搭积木一样简单
  • SM+办公软件核心功能解析与Windows系统安装部署指南
  • 题解:洛谷 U327333 Max Sum Plus Plus 2
  • 从Hello World到UVM:在CentOS 7虚拟机里用VCS跑通你的第一个SystemVerilog仿真
  • 2026年Q2上海大众搬家号码靠谱性实测分析:大众搬家公司电话/宝山大众搬家公司/家具衣橱床拆卸挪移服务/床拆卸打包服务/选择指南 - 优质品牌商家
  • 【独家首发】Perplexity未公开的心理健康API端点清单(含3类受限资源获取通道+OAuth2.0绕过验证备案流程)
  • 如何使用 SG 函数解决 2026 JSCPC L
  • 2026年第二季度,寻找可靠自行车公司?深度解析行业标杆途锐达right - 2026年企业推荐榜
  • ComfyUI IPAdapter CLIP Vision模型配置完全指南:从基础到高级应用
  • 告别环境配置噩梦:用Docker一键部署GPGPU-Sim模拟器(附避坑指南)
  • 番茄小说下载器:免费开源的多格式小说下载完整指南
  • 查看详细审计日志追溯API调用历史与异常访问
  • 2026年Q2智慧酒店物联网AI大数据核心服务商排行:弱电智能化品牌、弱电智能化报价、弱电智能化改造、弱电智能化方案选择指南 - 优质品牌商家
  • SAP 高级退货流程(供应商)的Fiori应用实战与核心配置解析
  • 嵌入式触摸屏亮度调节实战:从PWM调光原理到软硬件解决方案
  • 告别默认灰:用Qt5.14.2+VS2019和QSS三套皮肤,5分钟让你的Qt应用颜值飙升
  • 多 Agent 协作中人格冲突频发?Hermes Agent 的 4 类 SOUL/USER 分工策略
  • 书匠策AI到底是什么来头?毕业论文写作的“黑科技“我给你扒明白了
  • CAXA 正多边形命令
  • 高效解决Windows依赖问题的智能工具完全指南:Visual C++ Redistributable AIO深度解析
  • 简述从Gemma_4到DeepSeek_V4的架构演进
  • 保姆级教程:在Ubuntu 20.04上用kitti2bag工具把KITTI Raw Data转成ROS Bag(避坑实录)