[UOJ336]无限之环
题目的要求就是每个接头都有且仅有一个与其相连的接头,所以不妨给每个接头$1$的流量,对整个网格图黑白染色后(源点$\mathop\rightarrow\limits^\infty$黑点,白点$\mathop\rightarrow\limits^\infty$汇点)跑最大流即可,剩下的问题就是给旋转水管安排合适的费用
把网格中的格子和边都看成点,先对每个格子按照形状向四周连边$(1,0)$,然后用恰当的建图来表示费用和纠正流量
对$1$接头,转一次可以改变流量到相邻的两个接头,转两次可以改变流量到对面的接头
对$2$接头,转一次相当于把一个接头的流量改到对面,连了这两条边后发现恰好满足转两次的需求
对$3$接头,转一次相当于一个接头的流量改到相邻,转两次相当于将$3$个接头中间的接头改到对面,但因为每个接头都只能有$1$的流量经过,所以还要增加一点一边来限流
$4$接头就直接连了
总的来说就是两点:1.黑白染色确保能在网格上的边产生流量;2.考虑旋转造成的实际影响,进而构造相应的图
无解就是黑白格接头不相等或跑出来的最大流和黑格接头不相等
#include<stdio.h> #include<string.h> #include<queue> using namespace std; const int inf=2147483647,go[4][2]={{-1,0},{0,1},{1,0},{0,-1}}; int h[8010],nex[32010],to[32010],cap[32010],cos[32010],M=1,S,T; void ins(int a,int b,int c,int d){ M++; to[M]=b; cap[M]=c; cos[M]=d; nex[M]=h[a]; h[a]=M; } void add(int a,int b,int c,int d){ ins(a,b,c,d); ins(b,a,0,-d); } int dis[8010],sum,cost,N; struct pr{ int x,d; pr(int u=0):x(u),d(dis[u]){} }t; bool operator<(pr a,pr b){return a.d>b.d;} priority_queue<pr>q; bool bfs(){ int x,i; memset(dis,63,sizeof(dis)); dis[T]=0; q.push(T); while(!q.empty()){ t=q.top(); q.pop(); x=t.x; if(t.d!=dis[x])continue; for(i=h[x];i;i=nex[i]){ if(cap[i^1]&&dis[x]-cos[i]<dis[to[i]]){ dis[to[i]]=dis[x]-cos[i]; q.push(to[i]); } } } sum+=dis[S]; for(x=1;x<=N;x++){ for(i=h[x];i;i=nex[i])cos[i]+=dis[to[i]]-dis[x]; } return dis[S]!=dis[0]; } bool aug[8010]; int dfs(int x,int flow){ if(flow==0)return 0; if(x==T){ cost+=sum*flow; return flow; } int i,us=0,t; aug[x]=1; for(i=h[x];i&&flow;i=nex[i]){ if(cap[i]&&!cos[i]&&!aug[to[i]]){ t=dfs(to[i],min(flow,cap[i])); cap[i]-=t; cap[i^1]+=t; us+=t; flow-=t; } } if(!flow)aug[x]=0; return us; } int costflow(){ int s,w; s=0; do{ do{ memset(aug,0,sizeof(aug)); w=dfs(S,inf); s+=w; }while(w); }while(bfs()); return s; } int cnt[16],rot[16],n,m; int type(int x){ if(cnt[x]==2)return x==5||x==10?0:2; return cnt[x]; } int p(int x,int y){ return(x-1)*m+y; } int p(int x,int y,int f){ f&=3; if(f==0)return(x-1)*m+y+n*m; if(f==1)return(x-1)*(m+1)+y+1+n*m+(n+1)*m; if(f==2)return x*m+y+n*m; return(x-1)*(m+1)+y+n*m+(n+1)*m; } void gao(int a,int b,int c,int d,int f){ if(f) add(a,b,c,d); else add(b,a,c,d); } int main(){ int i,j,x,s1,s2; for(i=1;i<16;i++)cnt[i]=cnt[i>>1]+(i&1); rot[2]=1; rot[4]=2; rot[6]=1; rot[8]=3; rot[9]=3; rot[11]=3; rot[12]=2; rot[13]=2; rot[14]=1; scanf("%d%d",&n,&m); S=n*m+(n+1)*m+n*(m+1)+1; N=T=S+1; s1=s2=0; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ scanf("%d",&x); if(x==0)continue; if((i+j)&1){ s1+=cnt[x]; add(S,p(i,j),inf,0); }else{ s2+=cnt[x]; add(p(i,j),T,inf,0); } if(x==5){ gao(p(i,j),p(i,j,0),1,0,(i+j)&1); gao(p(i,j),p(i,j,2),1,0,(i+j)&1); } if(x==10){ gao(p(i,j),p(i,j,1),1,0,(i+j)&1); gao(p(i,j),p(i,j,3),1,0,(i+j)&1); } switch(type(x)){ case 1: gao(p(i,j),p(i,j,rot[x]),1,0,(i+j)&1); gao(p(i,j,rot[x]),p(i,j,rot[x]+1),1,1,(i+j)&1); gao(p(i,j,rot[x]),p(i,j,rot[x]+2),1,2,(i+j)&1); gao(p(i,j,rot[x]),p(i,j,rot[x]+3),1,1,(i+j)&1); break; case 2: gao(p(i,j),p(i,j,rot[x]),1,0,(i+j)&1); gao(p(i,j),p(i,j,rot[x]+1),1,0,(i+j)&1); gao(p(i,j,rot[x]),p(i,j,rot[x]+2),1,1,(i+j)&1); gao(p(i,j,rot[x]+1),p(i,j,rot[x]+3),1,1,(i+j)&1); break; case 3: gao(p(i,j),p(i,j,rot[x]),1,0,(i+j)&1); gao(p(i,j),p(i,j,rot[x]+1),1,0,(i+j)&1); gao(p(i,j),p(i,j,rot[x]+2),1,0,(i+j)&1); N++; gao(p(i,j,rot[x]),N,1,1,(i+j)&1); gao(p(i,j,rot[x]+1),N,1,2,(i+j)&1); gao(p(i,j,rot[x]+2),N,1,1,(i+j)&1); gao(N,p(i,j,rot[x]+3),1,0,(i+j)&1); break; case 4: gao(p(i,j),p(i,j,0),1,0,(i+j)&1); gao(p(i,j),p(i,j,1),1,0,(i+j)&1); gao(p(i,j),p(i,j,2),1,0,(i+j)&1); gao(p(i,j),p(i,j,3),1,0,(i+j)&1); break; } } } if(s1!=s2||costflow()!=s1) puts("-1"); else printf("%d",cost); }
[UOJ336]无限之环的更多相关文章
- Loj #2321. 「清华集训 2017」无限之环
Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...
- Noip模拟63 2021.9.27(考场惊现无限之环)
T1 电压机制 把题目转化为找那些边只被奇数环包含. 这样的话直接$dfs$生成一棵树,给每个点附上一个深度,根据其他的非树边都是返祖边 可以算出环内边的数量$dep[x]-dep[y]+1$,然后判 ...
- 【uoj336】【清华集训2017】无限之环
题目 描述 给出一个\(n*m\)的网格,每个格子里的水管可能向四个方向都有接口: 游戏的目的是不能让水管漏水,即所有接口都有另一个接口与之相接: 你一步可以将一个格子中的水管旋转\(90 ...
- 洛谷P4003 无限之环(infinityloop)(网络流,费用流)
洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...
- BZOJ5120 [2017国家集训队测试]无限之环 费用流
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ5120 题意概括 原题挺简略的. 题解 本题好难. 听了任轩笛大佬<国家队神犇>的讲课才 ...
- BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)
题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ...
- BZOJ5120 无限之环(费用流)
方案合法相当于要求接口之间配对,黑白染色一波,考虑网络流.有一个很奇怪的限制是不能旋转直线型水管,考虑非直线型水管有什么特殊性,可以发现其接口都是连续的.那么对于旋转水管,可以看做是把顺/逆时针方向上 ...
- LOJ2321. 「清华集训 2017」无限之环【费用流】
LINK 很好的一道网络里题 首先想插头DP的还是出门左转10分代码吧 然后考虑怎么网络流 首先要保证没有漏水 也就是说每个接口一定要有对应的接口 那么发现每个点只有可能和上下左右四个点产生联通关系 ...
- bzoj 5120 [2017国家集训队测试]无限之环——网络流
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5120 旋转的话相当于去掉一个插头.新增一个插头,所以在这两个插头之间连边并带上费用即可. 网 ...
随机推荐
- CART算法(转)
来源:http://www.cnblogs.com/pinard/p/6053344.html 作者:刘建平Pinard 对于C4.5算法,我们也提到了它的不足,比如模型是用较为复杂的熵来度量,使用了 ...
- TCP之Nagle算法与延迟ACK
(一)Nagle算法 为了减少网络中小分组的数目,减少网络拥塞的情况.Nagle算法要求在一条TCP连接上最多只能有一个未被确认的未完成小分组,在该分组ACK到达之前不能够发送其他的小分组,发送端需要 ...
- tenda t402 家庭版 有线路由器
使用快速向导: adsl(拨号)+用户名+密码 路由器后DMZ主机设置简单图解:http://wenku.baidu.com/view/94b9f0768e9951e79b8927ce.html 可 ...
- 安装:python+webdriver环境
安装:python+webdriver环境第一步:安装active-python,双击可执行文件,直接默认安装即可.第二步:安装selenium webdriver1. 打开cmd2. 命令为:pip ...
- 【LabVIEW技巧】工厂模式_简单工厂
前言 上一个文章介绍了如何学习LabVIEW OOP,简要的提及了一些OOP学习中注意的事项,许多文章的读者反映写的太范,后文会逐步缩小范围,讨论在LabVIEW中各个模式的应用. 工厂模式概述 工厂 ...
- HTML 知识点总结
HTML基本语法 HTML标签 单标签 <标签名>或<标签名 /> 双标签 <标签名>内容</标签名> 跟标签也叫元素(根元素) 属性 属性属于标签 一 ...
- linux 系统调用exec()
系统调用execve()对当前进程进行替换,替换者为一个指定的程序,其参数包括文件名(filename).参数列表(argv)以及环境变量(envp).exec函数族当然不止一个,但它们大致相同,在 ...
- linux命令(42):wc命令
Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...
- Django Ajax学习二之文件上传
基于Django实现文件上传 1. url路由配置 路径:C:\Users\supery\Desktop\day82\demo_ajax\demo_ajax\urls.py from django.c ...
- AC日记——[SDOI2010]大陆争霸 洛谷 P3690
[SDOI2010]大陆争霸 思路: dijkstra模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn ...