传送门

神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦

到底是得有怎样的脑回路才能一眼看去就是费用流啊……

建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图

首先,对于每一个水管的支管,有且仅有一个其他支管与他相连,那么就不会漏水了。用网络流的说法,就是要每个支管容量只能为1且必须满流

然而因为最优情况图可能会被分成好几个连通块,于是我们得强制所有相邻的格子都有流量才行(就是确保连通块不管怎么划分都能流)

那么黑白染色冷静一下……黑点连源,白点连汇

然后费用是因为旋转产生的……然后因为和四周都有连边所以要拆点

把每一个点拆成上下左右中,中间为原点,四周代表四个方向的水管。中间点连上源或汇,四周的点分别向能到达的接触点连边,容1费0

然后讨论旋转产生的费用……坐稳了……

先是直线型

比如射线指向上面,那么就让左下右的点连上面,左右点连边容1费1(转一次就行),下面的点连边容1费2(要转两次)

然后直角的

转一次会变成这样

那么就可以看做是上面的点跑到下面来了,那么上下建一条容1费1的边就好,左右同理。如果转了两次,刚好可以从上右一起流,费2,所以不用新加边了

最后第三种

如果顺时针转一次相当于左边到了下面,于是连边容1费1,同理下右连边容1费1,上下连边容1费2(因为上下转换要转两次)

然后其他都和以上一样分类讨论就行了

上代码吧,写的zkw费用流

  1. //minamoto
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<cstring>
  5. #include<queue>
  6. #define inf 0x3f3f3f3f
  7. using namespace std;
  8. #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  9. char buf[<<],*p1=buf,*p2=buf;
  10. inline int read(){
  11. #define num ch-'0'
  12. char ch;bool flag=;int res;
  13. while(!isdigit(ch=getc()))
  14. (ch=='-')&&(flag=true);
  15. for(res=num;isdigit(ch=getc());res=res*+num);
  16. (flag)&&(res=-res);
  17. #undef num
  18. return res;
  19. }
  20. #define UP(x) x+turn*sum
  21. #define RI(x) x+((turn+1)&3)*sum
  22. #define DO(x) x+((turn+2)&3)*sum
  23. #define LE(x) x+((turn+3)&3)*sum
  24. #define MD(x) x+(sum<<2)//上面几个用来计算对应点的数组下标,上下左右中。。。
  25. const int N=,M=;
  26. int sum,S=,T;
  27. int head[N],Next[M],ver[M],edge[M],cost[M],tot=;
  28. int dis[N],vis[N],cur[N],ans;
  29. int n,m,k=,totf,turn;
  30. inline void add(int u,int v,int e,int c,int tp){
  31. //tp表示点的颜色,如果是白点所有边都要反向,为了让流流向汇点
  32. if(tp) u^=v^=u^=v;
  33. ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,cost[tot]=c;
  34. ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=,cost[tot]=-c;
  35. }
  36. queue<int> q;
  37. bool spfa(){
  38. memset(dis,-,sizeof(dis));
  39. memset(vis,,sizeof(vis));
  40. memcpy(cur,head,sizeof(int)*(T-S+));
  41. q.push(T),dis[T]=,vis[T]=;
  42. while(!q.empty()){
  43. int u=q.front();q.pop(),vis[u]=;
  44. for(int i=head[u];i;i=Next[i])
  45. if(edge[i^]){
  46. int v=ver[i],c=cost[i];
  47. if(dis[v]<||dis[v]>dis[u]-c){
  48. dis[v]=dis[u]-c;
  49. if(!vis[v]) vis[v]=,q.push(v);
  50. }
  51. }
  52. }
  53. return ~dis[S];
  54. }
  55. int dfs(int u,int limit){
  56. if(u==T||!limit) return limit;
  57. int flow=,f;vis[u]=;
  58. for(int &i=cur[u];i;i=Next[i]){
  59. int v=ver[i];
  60. if(dis[v]==dis[u]-cost[i]&&!vis[v]&&(f=dfs(v,min(limit,edge[i])))){
  61. flow+=f,limit-=f;
  62. edge[i]-=f,edge[i^]+=f;
  63. ans+=f*cost[i];
  64. if(!limit) break;
  65. }
  66. }
  67. vis[u]=;
  68. return flow;
  69. }
  70. int zkw(){
  71. //zkw费用流板子
  72. int flow=;
  73. while(spfa()) flow+=dfs(S,inf);
  74. return flow;
  75. }
  76. int main(){
  77. // freopen("testdata.in","r",stdin);
  78. n=read(),m=read();
  79. sum=n*m,T=sum*+;
  80. for(int i=;i<n;++i)
  81. for(int j=;j<m;++j,++k){
  82. turn=;
  83. int t=(i+j)&;
  84. t?add(S,MD(k),inf,,):add(MD(k),T,inf,,);
  85. if(i) add(DO(k-m),UP(k),,,t);
  86. if(j) add(RI(k-),LE(k),,,t);
  87. int op=read();
  88. if(op&) add(UP(k),MD(k),,,t),++totf;
  89. if(op&) add(RI(k),MD(k),,,t),++totf;
  90. if(op&) add(DO(k),MD(k),,,t),++totf;
  91. if(op&) add(LE(k),MD(k),,,t),++totf;
  92. //统计一下总流量顺便和中间点连边
  93. //因为每条边被记了两次,到时候要除以2
  94. switch(op){
  95. //直接把所有相同类型的一起处理掉
  96. case :++turn;
  97. case :++turn;
  98. case :++turn;
  99. case :
  100. add(RI(k),UP(k),,,t);
  101. add(DO(k),UP(k),,,t);
  102. add(LE(k),UP(k),,,t);
  103. break;
  104. case :++turn;
  105. case :++turn;
  106. case :++turn;
  107. case :
  108. add(DO(k),UP(k),,,t);
  109. add(LE(k),RI(k),,,t);
  110. break;
  111. case :++turn;
  112. case :++turn;
  113. case :++turn;
  114. case :
  115. add(DO(k),LE(k),,,t);
  116. add(DO(k),UP(k),,,t);
  117. add(DO(k),RI(k),,,t);
  118. break;
  119. }
  120. }
  121. printf("%d\n",(zkw()<<)==totf?ans:-);
  122. return ;
  123. }

洛谷P4003 无限之环(费用流)的更多相关文章

  1. 洛谷P4003 无限之环(infinityloop)(网络流,费用流)

    洛谷题目传送门 题目 题目描述 曾经有一款流行的游戏,叫做 Infinity Loop,先来简单的介绍一下这个游戏: 游戏在一个 n ∗ m 的网格状棋盘上进行,其中有些小方格中会有水管,水管可能在格 ...

  2. BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)

    题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ...

  3. BZOJ5120 [2017国家集训队测试]无限之环 费用流

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ5120 题意概括 原题挺简略的. 题解 本题好难. 听了任轩笛大佬<国家队神犇>的讲课才 ...

  4. 洛谷.4015.运输问题(SPFA费用流)

    题目链接 嗯..水题 洛谷这网络流二十四题的难度评价真神奇.. #include <queue> #include <cstdio> #include <cctype&g ...

  5. 洛谷P4015 运输问题(费用流)

    传送门 源点向仓库连费用$0$,流量为储量的边,商店向汇点连费用$0$,流量为需求的边,然后仓库向商店连流量$inf$,费用对应的边,跑个费用流即可 //minamoto #include<io ...

  6. 洛谷P4014 分配问题(费用流)

    传送门 可以把原图看做一个二分图,人在左边,任务在右边,求一个带权的最大和最小完美匹配 然而我并不会二分图做法,所以只好直接用费用流套进去,求一个最小费用最大流和最大费用最大流即可 //minamot ...

  7. 洛谷 - P4452 - 航班安排 - 费用流

    https://www.luogu.org/problemnew/show/P4452 又一道看题解的费用流. 注意时间也影响节点,像题解那样建边就少很多了. #include<bits/std ...

  8. BZOJ 5120: [2017国家集训队测试]无限之环(费用流)

    传送门 解题思路 神仙题.调了一个晚上+半个上午..这道咋看咋都不像图论的题竟然用费用流做,将行+列为奇数的点和偶数的点分开,也就是匹配问题,然后把一个点复制四份,分别代表这个点的上下左右接头,如果有 ...

  9. bzoj 5120 无限之环 & 洛谷 P4003 —— 费用流(多路增广SPFA)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5120 https://www.luogu.org/problemnew/show/P4003 ...

随机推荐

  1. deepin网络加速

    0.进入控制中心里的“更新设置”,选择速度最快的镜像源(我的是阿里云)1.安装dnsmasq(命令:sudo aptitude install dnsmasq)2.以管理员权限打开gedit(命令:s ...

  2. the art of seo(chapter eleven)

    Tracking Results and Measuring Success goal -> driver ***Why Measuring Success Is Essential to th ...

  3. kettle脚本定时任务不执行

    问题描述:在centos机器上部署了kettle脚本,每天定时跑一次,但是并没有成功跑,手动执行命令是可以的.而且写了一个测试的shell脚本也是可以执行的. 解决方案: 将2的错误输出,/usr/l ...

  4. java-02 for循环,while循环

    ###############获取一个数字的每位数字############### #############1-100奇数和偶数和############## public class Sum { ...

  5. 「LOJ#10068」「一本通 3.1 练习 3」秘密的牛奶运输(次小生成树

    题目描述 Farmer John 要把他的牛奶运输到各个销售点.运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点. 运输的总距离越小,运输的成本也就越低.低成本的运输是 F ...

  6. ACM学习历程—Codeforces 446C DZY Loves Fibonacci Numbers(线段树 && 数论)

    Description In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence ...

  7. 【LeetCode】039. Combination Sum

    题目: Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all uniq ...

  8. 制定一套适合自己团队的GITflow标准化工作流

    Git作为分布式代码管理的“当红炸子鸡”,被越来越多团队使用.当团队多个人员在同一个Git仓库上进行代码开发,没有一套标准化流程,将会引起代码管理的混乱,上线流程的迷茫,影响工作效率.制定一套适合自己 ...

  9. 详解使用python crontab设置linux定时任务

    熟悉linux的朋友应该知道在linux中可以使用crontab设置定时任务.可以通过命令crontab -e编写任务.当然也可以直接写配置文件设置任务. 但是有时候希望通过脚本自动设置,比如我们应用 ...

  10. python script

    1.tab键自动补全(每次导入时要将脚本的路径加入到sys.path中) import sysimport readlineimport rlcompleterimport atexitimport ...