这几天敲了几道最大流的问题,发现网络流真是模板算法啊。。。。

敲来敲去敲了几遍,基本每遍都敲得让人灰心,但同时也感受到了网络流的强大所在,这是我做网络流的第一题,,本以为看了一遍小白书的代码差不多理解就可以A掉一题的,没想到打击不是一点点的少啊。。。。。

首先小白书将的邻接矩阵存边,这里必须用邻接表,而本以为随便改改就好的,没想到那个记录路径却让人头疼得要命,无赖之下看了题解,看到了一个名为SAP的强大算法,虽然比小白的代码量增加了不少,理解起来也不是很容易,但是复杂度真心减少了不知一点点啊!!!!

虽然履步维艰,最后慢慢看着大牛模板一点一点敲了出来,可是其实还不是特别的了解的说,只是大致明白了思路而已,没办法看不懂就背下来吧,相信敲得多了自然就会慢慢理解记住的。。。

下面的SAP代码风格是我在网上找了一些后自己最觉得满意的一种(看到很多人使用loop;goto语句,真心不想用那样的句子啊,真心强迫症患者啊。。。。)

(能有自己的网络流模板感觉真好~~~)

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <vector>
  8 #include <cstdio>
  9 #include <cctype>
 10 #include <cstring>
 11 #include <cstdlib>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15 #define INF 0x3f3f3f3f
 16 #define inf ((LL)1<<40)
 17 #define lson k<<1, L, mid
 18 #define rson k<<1|1, mid+1, R
 19 #define mem0(a) memset(a,0,sizeof(a))
 20 #define mem1(a) memset(a,-1,sizeof(a))
 21 #define mem(a, b) memset(a, b, sizeof(a))
 22 #define FOPENIN(IN) freopen(IN, "r", stdin)
 23 #define FOPENOUT(OUT) freopen(OUT, "w", stdout)
 24 template<class T> T ABS ( T a) { return a >= 0 ? a : -a;   }
 25 template<class T> T CMP_MIN ( T a, T b ) { return a < b;   }
 26 template<class T> T CMP_MAX ( T a, T b ) { return a > b;   }
 27 template<class T> T MAX ( T a, T b ) { return a > b ? a : b; }
 28 template<class T> T MIN ( T a, T b ) { return a < b ? a : b; }
 29 template<class T> T GCD ( T a, T b ) { return b ? GCD ( b, a % b ) : a; }
 30 template<class T> T LCM ( T a, T b ) { return a / GCD ( a, b ) * b;     }
 31 template<class T> void SWAP( T& a, T& b ) { T t = a; a = b;  b = t;     }
 32
 33 typedef __int64 LL;
 34 //typedef long long LL;
 35 const int MAXN = 101000;
 36 const int MAXM = 500100;
 37 const double eps = 1e-14;
 38 const double PI = 4.0 * atan(1.0);
 39 const LL MOD = 1000000007;
 40
 41 int dx[4] = {0, -1, 0, 1};
 42 int dy[4] = {1, 0, -1, 0};
 43
 44 int n, m, k, ma[55][55], mus[55][55], sum;
 45
 46 struct Edge { int to, cap, next; }edge[MAXM<<1];
 47 int head[MAXN], tot;
 48
 49 int src, des;
 50 int dep[MAXN], gap[MAXN], pre[MAXN], aug[MAXN], cur[MAXN];
 51
 52 void init()
 53 {
 54     int x, y;
 55     mem0(mus); mem0(edge);sum = 0;
 56     for(int i = 1; i <= n; i ++)
 57     {
 58         for(int j = 1; j <= m; j ++ )
 59         {
 60             scanf("%d", &ma[i][j]);
 61             sum += ma[i][j];
 62         }
 63     }
 64     for(int i = 0; i < k; i ++)
 65     {
 66         scanf("%d %d", &x, &y);
 67         mus[x][y] = 1;
 68     }
 69 }
 70
 71 void addEdge(int u, int v, int val)
 72 {
 73     edge[tot].to = v; edge[tot].cap = val;   edge[tot].next= head[u];
 74     head[u] = tot ++;
 75     edge[tot].to = u; edge[tot].cap = 0;     edge[tot].next = head[v];
 76     head[v] = tot ++;
 77 }
 78
 79 void init_Edge()
 80 {
 81     mem1(head); tot = 0;
 82     src = 0; des = m * n + 1;
 83     for(int i = 1; i <= n; i ++)
 84     {
 85         for(int j = 1; j <= m; j ++)
 86         {
 87             int now = (i-1)*m + j;
 88             if((i+j)&1){
 89                 if(mus[i][j]) addEdge(now, des, INF);
 90                 else addEdge(now, des, ma[i][j]);
 91             }
 92             else {
 93                 if(mus[i][j]) addEdge(src, now, INF);
 94                 else addEdge(src, now, ma[i][j]);
 95                 for(int k = 0; k < 4; k ++ ) {
 96                     int nx = i + dx[k], ny = j + dy[k];
 97                     if(nx>0 && nx<=n && ny>0 && ny<=m)
 98                         addEdge(now, (nx-1)*m+ny, 2*(ma[i][j]&ma[nx][ny]));
 99                 }
100             }
101         }
102     }
103 }
104
105 int SAP(int n)
106 {
107     mem0(aug);   mem0(pre);
108     mem(dep, 0); mem(gap, 0);
109     int max_flow = 0, u = src;
110     aug[src] = INF;
111     pre[src] = -1;
112     gap[0] = n;
113     for(int i = 0; i <= n; i ++)
114         cur[i] = head[i];
115     while(dep[src] < n)
116     {
117         //printf("%d\n", u);
118         if(u == des)
119         {
120           //  printf("%d\n", max_flow);
121             max_flow += aug[des];
122             for(int v = pre[des]; v != -1; v = pre[v])
123             {
124                 int e = cur[v];
125                 edge[e].cap   -= aug[des];
126                 edge[e^1].cap += aug[des];
127                 aug[v] -= aug[des];
128                 if(edge[e].cap == 0) u = v;
129                 //u = src;
130             }
131         }
132         int flag = 0;
133         for(int e = cur[u]; e != -1; e = edge[e].next)
134         {
135             int v = edge[e].to;
136             if(edge[e].cap > 0 && dep[u] == dep[v] + 1)
137             {
138                 flag = 1;
139                 pre[v] = u; cur[u] = e;
140                 aug[v] = MIN(aug[u], edge[e].cap);
141                 u = v;
142                 break;
143             }
144         }
145         if(!flag)
146         {
147             if(--gap[dep[u]] == 0)
148                 break;
149             int min_dep = n;
150             cur[u] = head[u];
151             for(int e = head[u]; e != -1; e = edge[e].next)
152             {
153                 int v = edge[e].to;
154                 if(edge[e].cap > 0 && dep[v] < min_dep)
155                 {
156                     min_dep = dep[v];
157                     cur[u] = e;
158                 }
159             }
160             dep[u] = min_dep + 1;
161             gap[dep[u]] ++;
162             if(u != src) u = pre[u];
163         }
164     }
165     return max_flow;
166 }
167
168 int main()
169 {
170     while(~scanf("%d %d %d", &n, &m, &k))
171     {
172         init();
173         init_Edge();
174         printf("%d\n", sum - SAP(des+1));
175     }
176     return 0;
177 }

转载于:https://www.cnblogs.com/gj-Acit/p/3926019.html

HDU3657Game(最大流)相关推荐

  1. stream流对象的理解及使用

    我的理解:用stream流式处理数据,将数据用一个一个方法去 . (点,即调用) 得到新的数据结果,可以一步达成. 有多种方式生成 Stream Source: 从 Collection 和数组 Co ...

  2. 如何判断飞机的年限_技术流带你鉴定前风挡玻璃更换,不再使用日期判断!

    ​ 这又是一篇关于前风挡玻璃鉴定的文章,我记得在二手车鉴定微信公众号里面已经发布好几篇这样的文章了,当然每篇文章的住重点不同,今天这一篇应该是完结篇,它们在一起能组成一套玻璃更换系列专题课程: 我们回 ...

  3. SpringCloud Alibaba微服务实战(五) - Sentinel实现限流熔断

    什么是Sentinel? 请查看文章:SpringCloud Alibaba微服务实战(一) - 基础环境搭建 构建服务消费者cloud-sentinel进行服务调用 服务创建请查看文章:Spring ...

  4. 文件流处理流式处理大数据处理

    20210315 https://www.yuque.com/7125messi/wydusr/wweetn 42-(重要重要重要)加速pandas(Modin和pandarallel) 重点 htt ...

  5. javaSE8的流库总结

    前言 本篇博客对 java 8 的流库进行一个总结 1. 从迭代到流 在处理集合时,我们通常会迭代遍历它的元素,并在每个元素上执行某项操作,列如假设我们想统计某本书的所有长单词数(单词长度大于10): ...

  6. CUDA 7流简化并发

    CUDA 7流简化并发 异构计算是指有效使用系统中的所有处理器,包括CPU和GPU.为此,应用程序必须在多个处理器上同时执行功能.CUDA应用程序通过在流(按顺序执行的命令序列)中,执行异步命令来管理 ...

  7. GPU编程和流式多处理器(二)

    GPU编程和流式多处理器(二) 2. 整数支持 SM具有32位整数运算的完整补充. • 加法运算符的可选否定加法 • 乘法与乘法加法 • 整数除法 • 逻辑运算 • 条件码操作 • to/from浮点 ...

  8. GPU编程和流式多处理器

    GPU编程和流式多处理器 流式多处理器(SM)是运行CUDA内核的GPU的一部分.本章重点介绍SM的指令集功能. 流式多处理器(SM)是运行我们的CUDA内核的GPU的一部分.每个SM包含以下内容. ...

  9. Cuda Stream流 分析

    Cuda Stream流分析 Stream 一般来说,cuda c并行性表现在下面两个层面上: • Kernel level • Grid level Stream和event简介 Cuda stre ...

最新文章

  1. jstl标签: c:Foreach详解
  2. c#如何通过ftp上传文件_定时上传文件到ftp,2步完成Windows系统定时上传文件到ftp...
  3. SQL Server通过web方式进行远程维护,管理
  4. id ajax,AJAX_ajax.js里面有内容显示效果,根据ID,ajax.js里面有内容显示效果,根 - phpStudy...
  5. ***帮兄设计实战分析
  6. Direct2D (25) : 将画笔线条所占用的区域转换为路径 - ID2D1Geometry.Widen()
  7. 对“纯手工编写的第一个Hibernate程序”的改进
  8. iphone计算机快捷键,苹果电脑快捷键大全,最常用的都在这里了
  9. Tensorflow在python3.7版本的运行并且在pycharm安装tensorflow(亲测)
  10. Android万年历课程设计,电子万年历的设计(课程设计)
  11. 如何替换SAP Spartacus启动Component -app-root
  12. .NET HttpClient的缺陷和文档错误让开发人员倍感沮丧
  13. 图像直方图原理与Python实现
  14. 大数据系列博客之 --- 深入简出 Shell 脚本语言(提升篇)
  15. 盘口的买一是卖股票还是买股票?
  16. Golang 之轻松化解 defer 的温柔陷阱
  17. 如何区分oracle服务器、oracle客户端、plsql?
  18. 多人语音聊天社交app源码,语音聊天的优势是什么,语音系统源码开发
  19. vue中使用echarts地图
  20. 前端安全(常见WEB攻击及防范)

热门文章

  1. 7 种常用的排序算法直观感受
  2. 理解“==”和“equals()”
  3. 描点链接元素的优化提升用户体验
  4. windows8不能更新?
  5. 无处不在的 AWS 云计算
  6. 计算机组成原理 — CPU 中央处理器
  7. 用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览
  8. U-Boot移植教程之一:U-Boot分析与启动过程
  9. PCB铜箔厚度、线宽与允许通多电流大小的关系
  10. .net的垃圾回收机制[转]