无限之环 题解

五星压行大师 \(lyh\) 表示:这是难得能让他的代码长度打破百行大关的题目(182行)。

首先,根据科技与狠活,本题可以黑白染色。源点联向白格,黑格连向汇点。

发现每个格子都可以连向四个方向,所以可以建立四个点,代表水管连到了上下左右四个方向。

设四元组 \((x,y,z,p)\) 表示水管初始状态下,是否联向上、右、下、左。若 \(x==1\),则从源点联向上点(黑格则从上点联向汇点),以此类推。

例如:格子是白格,代表的水管初始状态接口在上和右,我们就从源点联向格子上点和右点;格子是黑格,就从上点和右点联向汇点。

当然,相邻格子间的上下左右是相通的,要从白格的上下左右点联向上方格子的下点、下方格子的上点、左方格子的右点、右方格子的左点。

我们用样例 1 做例子:

由于这些边都是生来就有的,所以不用支付任何费用,流量都为 1,记为 \((1,0)\)

由于水管可以旋转,所以我们肯定还需要再连一些边。

当然,直水管不能旋转,十字型水管转了没用,所以不用考虑。

由于黑格只需要和白格反着来就可以,所以只讨论白格:

  1. Q形管(只伸出一根水管)
    我们以 \((1,0,0,0)\) 这样的水管为例。
    发现旋转一次可以到达左点或右点,两次可以到达下点。
    那么从上点向左、右点连 \((1,1)\),向下点连 \((1,2)\)

  2. T形管(伸出三根水管)
    我们以 \((1,1,1,0)\) 这样的水管为例。
    发现旋转一次上、下点为 0,两次右点为 0,而旋转后左点都为 1。
    因而可以看作上、下、右点变成了左点。
    根据 Q形管 思路,上点、下点、右点向左点连 \((1,1),(1,1),(1,2)\)

  3. L形管(伸出相邻两根水管)
    我们以 \((1,1,0,0)\) 这样的水管为例。
    根据上述思路,可以很快想到上点向下点连 \((1,1)\),右点向左点连 \((1,1)\)
    旋转两次相当于同时经过上面两条边,所以不连。

我们将完整版的图再画一下(新增蓝、粉边都是 \((1,1)\),其余为 \((1,2)\)):

假如不漏水,一定会经过 \(sm=\sum(x+y+z+p)\) 条边。

发现每一条增广路经过且只经过 2 条水管,所以当最大流 \(<sm\) 时,输出 -1。

其他情况下,答案即为最小费用。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=14005,M=30005;
int n,m,s,t,k=1,h[N],vis[N];
int to[M],nxt[M],w[M],f[M];
int lst[N],flw[N],dis[N],sm;
int sh(int u,int v){return 4*(u*m-m+v-1)+1;
}int xi(int u,int v){return 4*(u*m-m+v-1)+2;
}int zu(int u,int v){return 4*(u*m-m+v-1)+3;
}int yo(int u,int v){return 4*(u*m-m+v-1)+4;
}void add(int x,int y,int z,int a){w[++k]=z;f[k]=a;to[k]=y;nxt[k]=h[x];h[x]=k;f[++k]=-a;to[k]=x;nxt[k]=h[y];h[y]=k;
}queue<int>q;
int spfa(){while(q.size()) q.pop();memset(lst,-1,sizeof(lst));memset(vis,0,sizeof(vis));memset(dis,127,sizeof(dis));flw[s]=1e9;dis[s]=0;q.push(s);while(q.size()){int x=q.front();q.pop();vis[x]=0;for(int i=h[x];i;i=nxt[i]){int y=to[i],vl=w[i];if(vl&&dis[y]>dis[x]+f[i]){lst[y]=i;flw[y]=min(flw[x],vl);dis[y]=dis[x]+f[i];if(!vis[y])q.push(y),vis[y]=1;}}}return lst[t]!=-1;
}int mxflw,mncst;
void MCMF(){while(spfa()){mxflw+=flw[t];mncst+=dis[t]*flw[t];for(int i=t;i!=s;i=to[lst[i]^1])w[lst[i]]-=flw[t],w[lst[i]^1]+=flw[t];}if(mxflw*2!=sm) cout<<-1;else cout<<mncst; 
}void white(int l,int u,int v){if(u>1) add(sh(u,v),xi(u-1,v),1,0);if(u<n) add(xi(u,v),sh(u+1,v),1,0);if(v>1) add(zu(u,v),yo(u,v-1),1,0);if(v<m) add(yo(u,v),zu(u,v+1),1,0);if(!l) return;int x=0,y=0,z=0,p=0;if(l&1) x=1;if(l&2) y=1;if(l&4) z=1;if(l&8) p=1;sm+=x+y+z+p;if(x) add(s,sh(u,v),1,0);if(z) add(s,xi(u,v),1,0);if(p) add(s,zu(u,v),1,0);if(y) add(s,yo(u,v),1,0);if(x&&!y&&z&&!p) return;if(!x&&y&&!z&&p) return;if(x&&y&&z&&p) return;if(x&&!y&&!z&&!p){add(sh(u,v),xi(u,v),1,2);add(sh(u,v),zu(u,v),1,1);add(sh(u,v),yo(u,v),1,1);}if(!x&&y&&!z&&!p){add(yo(u,v),sh(u,v),1,1);add(yo(u,v),zu(u,v),1,2);add(yo(u,v),xi(u,v),1,1);}if(!x&&!y&&z&&!p){add(xi(u,v),sh(u,v),1,2);add(xi(u,v),zu(u,v),1,1);add(xi(u,v),yo(u,v),1,1);}if(!x&&!y&&!z&&p){add(zu(u,v),sh(u,v),1,1);add(zu(u,v),yo(u,v),1,2);add(zu(u,v),xi(u,v),1,1);}if(x&&y&&z&&!p){add(sh(u,v),zu(u,v),1,1);add(yo(u,v),zu(u,v),1,2);add(xi(u,v),zu(u,v),1,1);}if(x&&y&&!z&&p){add(sh(u,v),xi(u,v),1,2);add(yo(u,v),xi(u,v),1,1);add(zu(u,v),xi(u,v),1,1);}if(x&&!y&&z&&p){add(sh(u,v),yo(u,v),1,1);add(zu(u,v),yo(u,v),1,2);add(xi(u,v),yo(u,v),1,1);}if(!x&&y&&z&&p){add(xi(u,v),sh(u,v),1,2);add(yo(u,v),sh(u,v),1,1);add(zu(u,v),sh(u,v),1,1);}if(!x&&!y&&z&&p){add(xi(u,v),sh(u,v),1,1);add(zu(u,v),yo(u,v),1,1);}if(x&&y&&!z&&!p){add(sh(u,v),xi(u,v),1,1);add(yo(u,v),zu(u,v),1,1);}if(x&&!y&&!z&&p){add(sh(u,v),xi(u,v),1,1);add(zu(u,v),yo(u,v),1,1);}if(!x&&y&&z&&!p){add(xi(u,v),sh(u,v),1,1);add(yo(u,v),zu(u,v),1,1);}
}void black(int l,int u,int v){if(!l) return;int x=0,y=0,z=0,p=0;if(l&1) x=1;if(l&2) y=1;if(l&4) z=1;if(l&8) p=1;sm+=x+y+z+p;if(x) add(sh(u,v),t,1,0);if(z) add(xi(u,v),t,1,0);if(p) add(zu(u,v),t,1,0);if(y) add(yo(u,v),t,1,0);if(x&&!y&&z&&!p) return;if(!x&&y&&!z&&p) return;if(x&&y&&z&&p) return;if(x&&!y&&!z&&!p){add(xi(u,v),sh(u,v),1,2);add(zu(u,v),sh(u,v),1,1);add(yo(u,v),sh(u,v),1,1);}if(!x&&y&&!z&&!p){add(sh(u,v),yo(u,v),1,1);add(zu(u,v),yo(u,v),1,2);add(xi(u,v),yo(u,v),1,1);}if(!x&&!y&&z&&!p){add(sh(u,v),xi(u,v),1,2);add(zu(u,v),xi(u,v),1,1);add(yo(u,v),xi(u,v),1,1);}if(!x&&!y&&!z&&p){add(sh(u,v),zu(u,v),1,1);add(yo(u,v),zu(u,v),1,2);add(xi(u,v),zu(u,v),1,1);}if(x&&y&&z&&!p){add(zu(u,v),sh(u,v),1,1);add(zu(u,v),yo(u,v),1,2);add(zu(u,v),xi(u,v),1,1);}if(x&&y&&!z&&p){add(xi(u,v),sh(u,v),1,2);add(xi(u,v),yo(u,v),1,1);add(xi(u,v),zu(u,v),1,1);}if(x&&!y&&z&&p){add(yo(u,v),sh(u,v),1,1);add(yo(u,v),zu(u,v),1,2);add(yo(u,v),xi(u,v),1,1);}if(!x&&y&&z&&p){add(sh(u,v),xi(u,v),1,2);add(sh(u,v),yo(u,v),1,1);add(sh(u,v),zu(u,v),1,1);}if(!x&&!y&&z&&p){add(sh(u,v),xi(u,v),1,1);add(yo(u,v),zu(u,v),1,1);}if(x&&y&&!z&&!p){add(xi(u,v),sh(u,v),1,1);add(zu(u,v),yo(u,v),1,1);}if(x&&!y&&!z&&p){add(xi(u,v),sh(u,v),1,1);add(yo(u,v),zu(u,v),1,1);}if(!x&&y&&z&&!p){add(sh(u,v),xi(u,v),1,1);add(zu(u,v),yo(u,v),1,1);}
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n>>m;t=n*m*4+1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){int x;cin>>x;if((i+j)&1) black(x,i,j);else white(x,i,j);}MCMF();return 0;
}//spfa:它没有死透

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/721733.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7大系统之间的关系

7大系统之间的关系:MES(制造执行系统)、ERP(企业资源规划)、SCM(供应链管理)、WMS(仓库管理系统)、APS(高级计划和排程)、SCADA(监控控制与数据获取)、PLM(产品生命周期管理)

OpenAI正式发布第一个官方.NET版本库的测试版

尽管 Microsoft 和 OpenAI 长期以来一直是紧密相连的合作伙伴,但他们现在才开始为 .NET 开发人员发布官方 OpenAI 库,加入现有的社区库。这项工作的第一个测试版是支持 .NET 6 和 .NET Standard 2.0 的 OpenAI NuGet 包,现在是 2.0.0-beta.3 [1]版本,列出了大约 872,000 次…

玩转树莓派之系统安装篇

手头上刚好有一个树莓派4B介绍 树莓派是树莓派基金会下的一个明星产品(单板计算机),已经迭代到第五代了;它性能强大、开源、拓展性强、体积小,搞物联网开发的人基本都听说过这个玩意!笔者手上刚好有一块4B的板子,让我们一起来玩转树莓派 安装准备 硬件树莓派4B 4G内存版…

Keil uVersion 4单片机开发指南

MDK Keil uVersion 4使用教程,基于STC8H8K64U单片机1 软件安装 双击打开C51V901.exe弹出安装界面,点击Next>>点击同意协议勾选框,接着点击Next>>点击Browse...选择合适的目录,接着点击Next>>按要求填写相关信息,然后点击Next>>软件安装中,等待安…

读AI未来进行式笔记06自动驾驶技术

读AI未来进行式笔记06自动驾驶技术1. 跃层冲击 1.1. 每个社会其实都处于不同的楼层,往往处于更低楼层的社会,要承受来自更高楼层的社会发展带来的更大冲击 2. 驾驶 2.1. 开车时最关键的不是车,而是路 2.2. 人是比机器更脆弱的生命,最微…

嵌入式代码优化技巧

笔者多年来总结的嵌入式代码优化技巧内存管理技巧 1.C/C++工程应尽量避免深拷贝,尽量用浅拷贝(指针或者引用),如果指针需要频繁拷贝,用智能指针是一种不错的选择 2.启用内存池管理线程的内存开销,事先在堆里边分配好,然后快速使用 避免复杂的浮点运算 1.复杂的浮点运算尽…

软件版本那些事

软件发布版本的常见类型软件版本跟测试阶段或者软件的生命周期所处的阶段有关,一般有以下几个版本 alpha 内测版本,仅限团队内部测试使用,不对外公开。大多数软件产品在向公众发布之前都要经过多个步骤。alpha版本是该系统的一部分,用于开发高效、准确和无缺陷的软件程序。…

RT-Thread和Infineon主持的嵌入式网络应用开发沙龙

2023年12月9日 深圳市维也纳好眠国际酒店 由RT-Thread和Infineon主持的嵌入式网络应用开发沙龙主题 会议由RT-Thread && Infineon共同主持,PSoc62开发板现场演示从0到1搭建智能数据网关RT-Thread介绍 rt-thread社区负责人郭占鑫郭工介绍RT-Thread英飞凌合作伙伴介绍 英…

小白学开源

如何参与到GitHub开源项目中去第一步 访问程序员交友网站,注册GitHub账号,注册流程请自行了解,如果已有账户请登录第二步 在搜索框输入你想查找的项目,例如cjson第三步 选择你感兴趣的那个项目,这里选择排行最前的那个,它的收藏数有9.5k第四步 先点击Fork生成自己的子仓库…

RT-Thread Studio使用教程

RT-Thread工程开发教程,基于PSoc62开发板介绍 RT-Thread Studio是官方出品的一款专门针对RT-Thread嵌入式开发、部署、调试、测试的集成开发环境,它基于Eclipse开源项目开发,极大的提高了嵌入式开发者的开发效率,目前最新版本是2.26 下载 使用浏览器打开RT-Thread官网,选择…

一款.NET开源、免费、实用的多功能原神工具箱(改善桌面端玩家的游戏体验)

前言 今天大姚给大家分享一款.NET开源(MIT License)、免费、实用的多功能原神工具箱,旨在改善桌面端玩家的游戏体验:胡桃工具箱。工具箱介绍 胡桃工具箱是一款.NET开源(MIT License)、免费、实用的多功能原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游…

VisualStudio 如何 SSH 远程调试 Linux 的 dotnet 应用的启动

本文将告诉大家,如何使用 VisualStudio 2022 工具,通过 SSH 远程调试运行在 Linux 系统上的 dotnet 系应用的启动过程本文写于 2024.06.07 如果你阅读本文的时间距离本文编写的时间过于长,那本文可能包含过期的知识 当前的 VisualStudio 2022 不能和在 Windows 一样,在 Lin…