题目的要求就是每个接头都有且仅有一个与其相连的接头,所以不妨给每个接头$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);elseadd(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");elseprintf("%d",cost);
}

转载于:https://www.cnblogs.com/jefflyy/p/9820848.html

[UOJ336]无限之环相关推荐

  1. [清华集训2017]无限之环(网络流)

    很妙的一道题 对于每个格子,它合法与否,只跟它上下左右的相邻格子有关,所以可以想到黑白染色 (用 (i,j) 表示 i 行 j 列的格子,我把 (i+j) %2 == 0 的格子染成白色,把(i+j) ...

  2. 解题:2017清华集训 无限之环

    题面 费用流 把每种水管再拆出来四个方向的接头,然后根据水管的形状连出旋转时的代价.最后黑白染色成二分图,然后白点对应的接头向黑点对应的接头连边,源点向白点自己连边,黑点自己向汇点连边. 怎么连边?我 ...

  3. 「面试」缓存知识点大总结

    周末一刻 这周过的比较快,事情也比较多,依然无法阻挡我每周一浪的节奏. 先去了"杰论"的奶茶店,好不好喝不做评价,主要是捧个场,就感觉你们每次在文章下面点个赞一样. 这周还去了所谓 ...

  4. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  5. 清华集训2017题解

    ioi赛制好评QAQ 好像啥都记不得了就不写游记了 Day 1 1.1 生成树计数(tree.cpp) 1.1.1. 题意 ​ 有 n≤30000n≤30000 n \le 30000 个点,第 ii ...

  6. 一句话题解(20180210~)

    2.9 BZOJ 2006 [NOI2010]超级钢琴.这道题目几天之前就做了.做法是固定右端点,左端点在ST表上走,走法其实就是笛卡尔树的走法.完结撒花! BZOJ 1218 [HNOI2003]激 ...

  7. Mysql中的递归层次查询(父子查询,无限极查询)

    前言:最近面试的时候遇到公司要求只能用SQL来查询无限极的数据,不能用PHP程序做递归查询,现在分享方法. 下面给出一个function来完成的方法 下面是sql脚本,想要运行的直接赋值粘贴进数据库即 ...

  8. fc天使之翼2020修改版下载_海岛奇兵无限钻石修改版下载-海岛奇兵无限钻石修改版下载2020...

    海岛奇兵无限钻石修改版绝对是小伙伴们都在寻找的资源,修改众多资源,玩家可以解锁不同兵种建立更强大的部队啦!通过塔防与掠夺不断强化我方战力,合理运用策略至关重要,喜欢的朋友千万别错过! 修改无限钻石.金 ...

  9. 【骚气的动效】无限循环往下往复淡入淡出运动,通常用于向下箭头,提示用户可以往下滚动或者点击展开

    /* 无限循环往下往复淡入淡出运动 */%auto-down-animate {animation: auto-down-animate 1s ease-in-out infinite;-moz-an ...

最新文章

  1. 基础总结篇之一:Activity生命周期
  2. poj2503 Babelfish
  3. msql 数据去重,仅保留一条
  4. android 加载器loader详解
  5. 原生JS DOM操作方法汇总
  6. SQL 2005新增的几个函数之学习
  7. java日志——基本日志+高级日志
  8. PTA-7-2 统计字符出现次数 (20分)
  9. SQLite字符串拼接
  10. YOLOv3: An Incremental Improvement
  11. 浅谈缓冲区溢出之栈溢出上
  12. .ani动态鼠标指针图像无法显示
  13. 代码自动生成-宏带来的奇计淫巧
  14. php+redis+保存多个值,php向redis list一次性lPush多个值
  15. 计算机顶级会议排名以及英文投稿的一点经验
  16. 免费公共DNS服务器大全
  17. 推荐一个美中不失优雅的博客网主页(素材参考---麋鹿鲁哟)
  18. 洛谷P1007独木桥题解--zhengjun
  19. Linux驱动子系统之I2C(一)
  20. ftk挂载镜像 加vm 实现仿真

热门文章

  1. 舍选法抽样matlab,舍选抽样法.PPT
  2. blender怎么移动骨骼_宝宝偏头怎么办?千万别错过这个矫正“黄金期”!
  3. LoadRunner第一次压测实践后的心得体会 收获
  4. java dom4j 写xml文件_Java实现——Dom4j读写XML文件
  5. 学会这篇文章分享的知识,你就超过了90%的测试人
  6. python收集参数_Python 中函数的 收集参数 机制
  7. set集合判断集合中是否有无元素_第八章 集合
  8. layui tree ajax刷新,layer 刷新某个页面的实现方法
  9. DaNet: Decompose-and-aggregate Network for 3D Human Shape and Pose Estimation
  10. qt-opensource-windows-x86-vs2010-4.8.6 + qt-creator-windows-opensource-2.8.0