前置知识

平面图

平面图就是平面上任意边都不相交的图。(自己瞎画的不算XD)

对偶图

比如说这个图,我们发现平面图肯定会把平面分成不同的区域(感觉像拓扑图),并把这些区域当做每个点(不被包围的区域独自成点,如本图4*),给相邻的区域连上边,就转化成了一个对偶图(图中红色)

网络流的图中有两个点:原点和汇点。割就是删去的一些边使原点和汇点无法连接(不太严谨)

看题!bzoj1001

既然有了原点和汇点,那么就不能简单的把外部看做一个点了,我们把外部分成两个点——超级原点和超级汇点!

然后像上面一样建边,求对偶图的最短路就行了!!!

你问我如何判断对偶图的点之间割了哪些边?

emmm这就是它恶心的地方了——建图并不容易。不过,它给边的方式还是有点人性的。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cctype>
  5. #include<cstring>
  6. #include<utility>
  7. #include<queue>
  8. #include<functional>
  9. #include<vector>
  10. using namespace std;
  11. inline int read()
  12. {
  13. int x=0,w=0;char c=getchar();
  14. while(!isdigit(c))w|=c=='-',c=getchar();
  15. while(isdigit(c) )x=(x<<3)+(x<<1)+(c^48),c=getchar();
  16. return w?-x:x;
  17. }
  18. const int maxn=3000000;
  19. typedef pair<int,int> pii;
  20. int n,m,node[1210][1210][2];
  21. int ecnt,t[maxn<<1],nxt[maxn<<1],head[maxn<<1],val[maxn<<1];
  22. inline void addedge(int from,int to,int dis)
  23. {
  24. t[++ecnt]=to;nxt[ecnt]=head[from];head[from]=ecnt;val[ecnt]=dis;
  25. t[++ecnt]=from;nxt[ecnt]=head[to];head[to]=ecnt;val[ecnt]=dis;
  26. }
  27. int dis[maxn];
  28. bool vis[maxn];
  29. inline void dijkstra(int start,int end)
  30. {
  31.  
  32. memset(dis,0x3f3f3f3f,sizeof dis);
  33. priority_queue<pii,vector<pii >,greater<pii > > q;
  34. q.push(make_pair(0,start)),dis[start]=0;
  35. while(!q.empty())
  36. {
  37. int u=q.top().second;q.pop();
  38. if(vis[u])continue;
  39. vis[u]=1;
  40. for(int i=head[u];i;i=nxt[i])
  41. {
  42. int v=t[i],w=val[i];
  43. if(dis[v]>=dis[u]+w)
  44. {
  45. dis[v]=dis[u]+w;
  46. q.push(make_pair(dis[v],v));
  47. }
  48. }
  49. }
  50. }
  51. int main()
  52. {
  53. int v=1;
  54. n=read()-1,m=read()-1;
  55. for(int i=1;i<=n;i++)
  56. for(int j=1;j<=m;j++)
  57. for(int k=0;k<2;k++)
  58. node[i][j][k]=v++;
  59. int start=v++,end=v;
  60. for(int j=1;j<=m;j++)addedge(start,node[1][j][0],read());
  61. for(int i=1;i<=n-1;i++)
  62. for(int j=1;j<=m;j++)
  63. addedge(node[i][j][1],node[i+1][j][0],read());
  64. for(int j=1;j<=m;j++)addedge(end,node[n][j][1],read());
  65. /*横行*/
  66. for(int i=1;i<=n;i++)
  67. for(int j=1;j<=m+1;j++)
  68. if(j==1)addedge(end,node[i][j][1],read());
  69. else if(j==m+1)addedge(start,node[i][j-1][0],read());
  70. else addedge(node[i][j-1][0],node[i][j][1],read());
  71. /*纵行*/
  72. for(int i=1;i<=n;i++)
  73. for(int j=1;j<=m;j++)
  74. addedge(node[i][j][0],node[i][j][1],read());
  75. /*斜行*/
  76. dijkstra(start,end);
  77. printf("%d\n",dis[end]);
  78. return 0;
  79. }

好了,以上只是针对bzoj1001的问题的解法。实际上,这个问题还有一些通用的解法(只不过出题人不想让大家用加强了数据)

不过上一道题我们也可以用下面的方式求出网络的最小割。

不过我们换一题XD

P2598狼和羊的故事

(反正狼就是nb)

通过读题,我们发现,这个orez想圈养狼真是了不起(姜戎都不敢这么干)

最大流最小割定理:网络的最大流等于最小割

证明也比较简单(但我不会严谨的),感性理解一下,最大流一定有一些边是满的,我们把这些边割了它就流不成了。对于其他的边,要么不是必经之路,要么边权不比同一条流上的最大流的边小,所以~~得证~~

那么这道题的话其他前辈已经讲得很好了,即求法就是

1. 将所有狼连到原点,边权INF
2. 将所有羊连到汇点,边权INF
3. 将所有点的四周加边,边权为1

这是一个对偶图的思想,相当于组成了一个网络,在这个网络中,只要点与点之间有边相连就相当于之间没有栅栏,所以一开始是全部连接的。我们要做的,就是砌栅栏把一些边断掉,使狼和羊分离。因为所有狼和所有羊都连在原点和汇点,这就相当于求最小割了。
(不知道讲清楚没有)

前面两个大家应该都清楚,边权INF相当于没有影响只是把所有狼/羊连在一起罢了。第三步就是连边:因为修一个栅栏需要1,所以边权为1,简直和对偶图一模一样(本来就是一个思想)
同样的,这里的难度就在于建边,建完求最大流就行了。

注意数组的大小。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cctype>
  6. #include<utility>
  7. #include<queue>
  8. using namespace std;
  9. inline int read()
  10. {
  11. int w=0,x=0;char c=getchar();
  12. while(!isdigit(c))w|=c=='-',c=getchar();
  13. while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
  14. return w?-x:x;
  15. }
  16. namespace star
  17. {
  18. const int maxn=100005,INF=0x3f3f3f3f;
  19. int n,m;
  20. int mapp[105][105];
  21. int ecnt=1,head[maxn],t[maxn<<1],nxt[maxn<<1],val[maxn<<1];
  22. inline void addedge(int from,int to, int dis)
  23. {
  24. t[++ecnt]=to;val[ecnt]=dis;nxt[ecnt]=head[from];head[from]=ecnt;
  25. t[++ecnt]=from;val[ecnt]=0;nxt[ecnt]=head[to];head[to]=ecnt;
  26. }
  27. int fx[]={0,1,0,-1},fy[]={1,0,-1,0};
  28. int cnt;
  29. int dep[maxn],start,end,cur[maxn];
  30. inline bool BFS()
  31. {
  32. queue<int> q;
  33. for(int i=1;i<=cnt;i++)dep[i]=-1,cur[i]=head[i];
  34. dep[start]=0;
  35. q.push(start);
  36. while(!q.empty())
  37. {
  38. int u=q.front();q.pop();
  39. for(int i=head[u];i;i=nxt[i])
  40. if(val[i] and dep[t[i]]==-1)
  41. dep[t[i]]=dep[u]+1,q.push(t[i]);
  42. }
  43. if(dep[end]==-1)return 0;
  44. return 1;
  45. }
  46.  
  47. int DFS(int x,int flow)
  48. {
  49. if(x==end)return flow;
  50. int used=0;
  51. for(int i=cur[x];i;i=nxt[i])
  52. {
  53. cur[x]=i;
  54. int u=t[i];
  55. if(val[i] and dep[u]==dep[x]+1)
  56. {
  57. int w=DFS(u,min(val[i],flow-used));
  58. used+=w;
  59. val[i]-=w;
  60. val[i^1]+=w;
  61. if(used==flow)return flow;
  62. }
  63. }
  64. if(!used)dep[x]=-1;
  65. return used;
  66. }
  67. inline void build()
  68. {
  69. n=read(),m=read();
  70. cnt=0;
  71. for(int i=1;i<=n;i++)
  72. for(int j=1;j<=m;j++)
  73. mapp[i][j]=++cnt;
  74. start=++cnt,end=++cnt;
  75. for(int zp,i=1;i<=n;i++)
  76. for(int j=1;j<=m;j++)
  77. if((zp=read())==1)addedge(start,mapp[i][j],INF);
  78. else if(zp==2)addedge(mapp[i][j],end,INF);
  79. for(int i=1;i<=n;i++)
  80. for(int j=1;j<=m;j++)
  81. for(int k=0;k<4;k++)
  82. {
  83. int xx=i+fx[k],yy=j+fy[k];
  84. if(xx<1 or xx>n or yy<1 or yy>m)continue;
  85. addedge(mapp[i][j],mapp[xx][yy],1);
  86. }
  87. }
  88. inline void work()
  89. {
  90. build();
  91. int ans=0;
  92. while(BFS())ans+=DFS(start,INF);
  93. printf("%d\n",ans);
  94. }
  95. }
  96. int main()
  97. {
  98. star::work();
  99. return 0;
  100. }

最大流最小割——bzoj1001狼抓兔子,洛谷P2598的更多相关文章

  1. bzoj1001狼抓兔子 对偶图优化

    bzoj1001狼抓兔子 对偶图优化 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1001 思路 菜鸡总是要填坑的! 很明显让你求网格图的最 ...

  2. 【bzoj1001】【最短路】【对偶图】【最大流转最小割】狼抓兔子题解

    [BZOJ1001]狼抓兔子 1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 18872  Solved ...

  3. BZOJ-1001 狼抓兔子 (最小割-最大流)平面图转对偶图+SPFA

    1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MB Submit: 14686 Solved: 3513 [Submit][ ...

  4. BZOJ1001:狼抓兔子(最小割最大流+vector模板)

    1001: [BeiJing2006]狼抓兔子 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨, ...

  5. bzoj1001狼抓兔子

    1001: [BeiJing2006]狼抓兔子 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你 ...

  6. BZOJ1001 狼抓兔子 平面图转对偶图 最小割

    现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为 ...

  7. BZOJ1001 狼抓兔子(裸网络流)

    Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一 ...

  8. 【建图+最短路】Bzoj1001 狼抓兔子

    Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个 ...

  9. [日常摸鱼]bzoj1001狼抓兔子-最大流最小割

    题意就是求最小割- 然后我们有这么一个定理(最大流-最小割定理 ): 任何一个网络图的最小割中边的容量之和等于图的最大流. (下面直接简称为最大流和最小割) 证明: 如果最大流>最小割,那把这些 ...

随机推荐

  1. 太神奇了!GIF的合成与提取这么好玩

    今天辰哥教大家一个Python有趣好玩的小功能:将多张图片转为GIF,同时也可以将一个GIF动图提取出里面的图片 在开始之前,先来一个动图开头(预览) 01.图片转GIF动图 1.准备工作 在开始合并 ...

  2. 「题解」300iq Contest 2 B Bitwise Xor

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:gym102331B. 题意概述 给你一个长度为 \(n\) 的序列 \(a_i\),求一个最长的子序列满足所有子序列中的 ...

  3. 四、SSL虚拟证书

    沿用练习三,配置基于加密网站的虚拟主机,实现以下目标: 域名为www.c.com 该站点通过https访问 通过私钥.证书对该站点所有数据加密 4.2 方案 源码安装Nginx时必须使用--with- ...

  4. WebClient (史上最全)

    疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 面试必备 + 面试必备 [博客园总入口 ] 疯狂创客圈 经典图书 : <Sprin ...

  5. css基本内容笔记(学习整理)

    一.css简介 1.什么是css 层叠样式表. 层叠:层层叠加,若果有冲突应用优先级高,不冲突的部分共同作用 样式表:就是css属性样式的集合: 2.作用 a.修饰html,使得html样式更好看 b ...

  6. git stash回退

    目录 1.起因 2. 问题出现 3.修复 4. 注意 1.起因 这个问题要从今天刚遇到的事儿说起,昨晚代码出了个乌龙事件,本来正在dev分支进行新功能的开发,但是测试出现的问题是在release 分支 ...

  7. 可编程网络DataPath 及XDP

    目录 可编程网络DataPath XDP 的基本架构 XDP 的软件要求 XDP 的硬件要求 XDP 的工作流程及使用 XDP 的工作模式 XDP 的工作流程 Hello World XDP 的应用 ...

  8. 聊聊 Feign 的实现原理

    What is Feign? Feign 是⼀个 HTTP 请求的轻量级客户端框架.通过 接口 + 注解的方式发起 HTTP 请求调用,面向接口编程,而不是像 Java 中通过封装 HTTP 请求报文 ...

  9. Linux云计算-01_介绍以及Linux操作系统安装

    1 学习目的 兴趣爱好 技能提升 找到满意的工作 2 什么是云计算 云计算(cloud computing)是分布式计算的一种,指的是通过网络"云"将巨大的数据计算处理程序分解成无 ...

  10. web自动化页面元素不能键盘输入

    一.背景 web自动化中存在一部分元素属性是readonly属性,导致我们在使用自动化代码的时候无法使用sendkeys()方法传入数据,以12306网站选择出发日期为例,见下图 二.json语句处理 ...