【uoj336】【清华集训2017】无限之环
题目
描述
 给出一个\(n*m\)的网格,每个格子里的水管可能向四个方向都有接口;
 游戏的目的是不能让水管漏水,即所有接口都有另一个接口与之相接;
 你一步可以将一个格子中的水管旋转\(90^ {\circ}\),规定直线型的接口不能旋转;
 求最小的步数;
范围
 \(nm \le 2000\);
题解
- 对每个点拆成上右下左四个接口(令标号为0123),将格子黑白染色并将接口分别向源汇连边; 
- 对每种形状的水管分类讨论,用 \((a,b,w)\) 表示在内部连边,仅讨论黑格子,白格子类似: - 0 型:(0,1,1)(0,3,1)(0,2,2)
- 01型:(0,2,1)(1,3,1)
- 012型:(0,3,1)(2,3,1)(1,3,2)
- 其他型:内部不需要连边
 
- 主要思想是讨论每种形状转来转去时候的代价; - #include<bits/stdc++.h>
 #define I(i,j,k) (k*n*m+(i-1)*m+j)
 #define inf 0x3f3f3f3f
 using namespace std;
 const int N=40010;
 int n,m,o,hd[N],S,T,que[N],head,tail,vis[N],dis[N];
 struct Edge{int v,nt,f,w;}E[N<<2];
 void adde(int u,int v,int c,int w){
 E[o]=(Edge){v,hd[u],c,w};hd[u]=o++;
 E[o]=(Edge){u,hd[v],0,-w};hd[v]=o++;
 }
 void add(int i,int j,int k1,int k2,int w){
 if((i+j)&1)adde(I(i,j,k1),I(i,j,k2),1,w);
 else adde(I(i,j,k2),I(i,j,k1),1,w);
 }
 bool spfa(){
 for(int i=S;i<=T;++i)vis[i]=0,dis[i]=inf;
 head=0;tail=1;vis[que[0]=T]=1;dis[T]=0;
 while(head!=tail){
 int u=que[head++];if(head==T)head=0;
 vis[u]=0;
 for(int i=hd[u];~i;i=E[i].nt)if(E[i^1].f){
 int v=E[i].v;
 if(dis[v]>dis[u]+E[i^1].w){
 dis[v]=dis[u]+E[i^1].w;
 if(!vis[v]){
 vis[v]=1,que[tail++]=v;
 if(tail==T)tail=0;
 }
 }
 }
 }
 return dis[S]!=inf;
 }
 int dfs(int u,int F){
 vis[u]=1;
 if(u==T||!F)return F;
 int flow=0,f;
 for(int i=hd[u];~i;i=E[i].nt){
 int v=E[i].v;
 if(!vis[v]&&dis[u]==dis[v]+E[i].w&&E[i].f&&(f=dfs(v,min(E[i].f,F)))){
 flow+=f;F-=f;
 E[i].f-=f;E[i^1].f+=f;
 if(!F)break;
 }
 }
 return flow;
 }
 int main(){
 // freopen("infinityloop.in","r",stdin);
 // freopen("infinityloop.out","w",stdout);
 scanf("%d%d",&n,&m);
 S=0;T=n*m*4+1;
 for(int i=S;i<=T;++i)hd[i]=-1;
 int mxf=0;
 for(int i=1;i<=n;++i)
 for(int j=1;j<=m;++j)if((i+j)&1){
 if(i!=1)adde(I(i,j,0),I(i-1,j,2),1,0);
 if(j!=1)adde(I(i,j,3),I(i,j-1,1),1,0);
 if(i!=n)adde(I(i,j,2),I(i+1,j,0),1,0);
 if(j!=m)adde(I(i,j,1),I(i,j+1,3),1,0);
 }
 int mx1=0,mx2=0;
 for(int i=1;i<=n;++i)
 for(int j=1;j<=m;++j){
 int x;scanf("%d",&x);
 if((i+j)&1)mx1+=__builtin_popcount(x);
 else mx2+=__builtin_popcount(x);
 for(int k=0;k<4;++k)if(x>>k&1){
 if((i+j)&1)adde(S,I(i,j,k),1,0);
 else adde(I(i,j,k),T,1,0);
 }
 switch (x){
 case 1:add(i,j,0,1,1);add(i,j,0,3,1);add(i,j,0,2,2);break;
 case 2:add(i,j,1,0,1);add(i,j,1,2,1);add(i,j,1,3,2);break;
 case 4:add(i,j,2,1,1);add(i,j,2,3,1);add(i,j,2,0,2);break;
 case 8:add(i,j,3,0,1);add(i,j,3,2,1);add(i,j,3,1,2);break; case 3:add(i,j,0,2,1);add(i,j,1,3,1);break;
 case 6:add(i,j,1,3,1);add(i,j,2,0,1);break;
 case 9:add(i,j,0,2,1);add(i,j,3,1,1);break;
 case 12:add(i,j,2,0,1);add(i,j,3,1,1);break; case 7:add(i,j,0,3,1);add(i,j,2,3,1);add(i,j,1,3,2);break;
 case 11:add(i,j,1,2,1);add(i,j,3,2,1);add(i,j,0,2,2);break;
 case 13:add(i,j,0,1,1);add(i,j,2,1,1);add(i,j,3,1,2);break;
 case 14:add(i,j,1,0,1);add(i,j,3,0,1);add(i,j,2,0,2);break; //case 0:break;
 //case 5:break;
 //case 10:break;
 //case 15:break;
 }
 }
 if(mx1!=mx2){puts("-1");return 0;}
 int flow=0,cost=0,f;
 while(spfa()){
 do{
 for(int i=S;i<=T;++i)vis[i]=0;
 f=dfs(S,inf);
 flow+=f;
 cost+=f*dis[S];
 }while(vis[T]);
 }
 if(flow!=mx1)puts("-1");
 else printf("%d\n",cost);
 return 0;
 }
 
【uoj336】【清华集训2017】无限之环的更多相关文章
- BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)
		题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ... 
- [清华集训2017]无限之环(infinityloop)
		description 题面 solution 一开始的思路是插头\(DP\),然而复杂度太高 考虑将网格图黑白染色后跑费用流 流量为接口数,费用为操作次数 把一个方格拆成五个点,如何连边请自行脑补 ... 
- LOJ 2321 清华集训2017 无限之环 拆点+最小费用最大流
		题面:中文题面,这里不占用篇幅 分析: 看到题面,我就想弃疗…… 但是作为任务题单,还是抄了题解…… 大概就是将每个格子拆点,拆成五个点,上下左右的触点和一个负责连源汇点的点(以下简称本点). 这个这 ... 
- Loj #2321. 「清华集训 2017」无限之环
		Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ... 
- [LOJ#2330]「清华集训 2017」榕树之心
		[LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ... 
- [LOJ#2329]「清华集训 2017」我的生命已如风中残烛
		[LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ... 
- Loj #2331. 「清华集训 2017」某位歌姬的故事
		Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ... 
- Loj #2324. 「清华集训 2017」小 Y 和二叉树
		Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ... 
- Loj 2320.「清华集训 2017」生成树计数
		Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ... 
- 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)
		[UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ... 
随机推荐
- JAVA核心:内存、比较和Final
			1.java是如何管理内存的 java的内存管理就是对象的分配和释放问题.(其中包括两部分) 分配:内存的分配是由程序完成的,程序员需要通过关键字new为每个对象申请内存空间(基本类型除外),所有的对 ... 
- 分布式监控系统Zabbix-3.0.3-完整安装记录(3)-监控nginx,php,memcache,Low-level discovery磁盘IO
			前段时间在公司IDC服务器上部署了zabbix3.0.3监控系统,除了自带的内存/带宽/CPU负载等系统资源监控模板以及mysql监控模板外,接下来对诸如nginx.php.memcache.磁盘IO ... 
- Centos6.5网络配置
			由于项目部署的需要,不得不继续研究Linux,前期看过一些Linux方面的资料,也动手配置过Linux网络配置,但是由于开发项目一般在windows下进行的,用Linux比较少,所以基本上也就忘记以前 ... 
- linux-RPM安装
			vh可写可不写 
- JS 实现计算一段文字中的字节数,字母数,数字数,行数,汉字数。
			看到了匹配,第一个想到了用正则表达式,哈哈,果然很方便.不过正则表达式高深莫测!我还没有研究明白啊..目前学了点皮毛.代码如下: <!DOCTYPE html PUBLIC "-//W ... 
- 【个人阅读】软件工程M1/M2阶段总结
			这次作业是好久以前布置的,由于学期末课程设计任务比较重,我在完善M2阶段的代码的同时又忙于数据库的实现和编译器的实现,一度感觉忙得透不过气来....到这些都基本完成的时候,会看自己以前的阅读心得,觉得 ... 
- APP推广(预期方案)
			首先,在推广过程中有一些定的弊端:我们这个O2O平台暂时只能适用于学校局域网. 因为我们的APP才刚刚“出炉”不久,在网络上还是属于一篇空白的状态,我们想过可以在百度百科上进行相应的推广,如果有用户搜 ... 
- Linux虚拟机下与主机通信
			1.更改虚拟机ip和主机ip同一网段 2.配置虚拟机的网络适配器 3.主机进行ping测试 
- Aop事务小结(事务管理器和自身构建)
			声明市事务是利用AOP来实现的. 1.采用事务管理器AOP: <!--3.配置事务切面:控制住连接池 --> <bean id="transactionManager&qu ... 
- shell脚本--continue、break
			shell中的continue和break和其他语言中的使用方法一模一样:continue用于跳过本次循环,break用于中断本层的循环 下面是使用例子: #!/bin/bash #文件名:test. ... 
