博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【洛谷 P3227】 [HNOI2013]切糕(最小割)
阅读量:4360 次
发布时间:2019-06-07

本文共 2619 字,大约阅读时间需要 8 分钟。

每层每个位置向下一层这个位置连边,流量为下一层这个位置的\(f\),源点向第一层连,流量第一层每个位置的费用,最后一层向汇点连,流量\(INF\)

这样就得到了\(P*Q\)条链,不考虑\(D\)的限制的话求最小割就是答案。
现在加入限制。记结论吧,我也不知道什么原理
每个位置从\(i=D+1\)层开始,向他前后左右第\(i-D\)层连边,流量\(INF\)
然后求出最小割即为答案。

#include 
#include
#include
#define INF 2147483647using namespace std;const int MAXN = 900010;const int MAXM = 2000010;inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') w = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * w;}struct Edge{ int next, to, rest;}e[MAXM];int s, t, num = 1, n, m, a, b, c, p, q, r, d, f[45][45][45];int head[MAXN];inline void Add(int from, int to, int flow){ e[++num] = (Edge){ head[from], to, flow }; head[from] = num; e[++num] = (Edge){ head[to], from, 0 }; head[to] = num;}int level[MAXN], now, sum;queue
Q;int re(){ memset(level, 0, sizeof level); while(Q.size()) Q.pop(); Q.push(s); level[s] = 1; while(Q.size()){ now = Q.front(); Q.pop(); for(int i = head[now]; i; i = e[i].next) if(e[i].rest && !level[e[i].to]){ level[e[i].to] = level[now] + 1; Q.push(e[i].to); } } return level[t];}int findflow(int u, int flow){ if(!flow || u == t) return flow; int f = 0, t; for(int i = head[u]; i; i = e[i].next){ if(e[i].rest && level[e[i].to] == level[u] + 1){ f += (t = findflow(e[i].to, min(flow - f, e[i].rest))); e[i].rest -= t; e[i ^ 1].rest += t; } } if(!f) level[u] = 0; return f;}int dinic(){ int ans = 0; while(re()) ans += findflow(s, INF); return ans;}int id(int k, int i, int j){ if(!k) return s; return (k - 1) * (p * q) + (i - 1) * q + j;}int L[] = {233, -1, 1, 0, 0}, R[] = {666, 0, 0, -1, 1};int main(){ p = read(); q = read(); r = read(); d = read(); s = 899999; t = 900000; for(int i = 1; i <= p; ++i) for(int j = 1; j <= q; ++j) Add(id(r, i, j), t, INF); for(int k = 1; k <= r; ++k) for(int i = 1; i <= p; ++i) for(int j = 1; j <= q; ++j) Add(id(k - 1, i, j), id(k, i, j), read()); for(int i = 1; i <= p; ++i) for(int j = 1; j <= q; ++j) for(int k = 1; k <= 4; ++k){ int x = i + L[k], y = j + R[k]; if(!x || !y || x > p || y > q) continue; for(int o = d + 1; o <= r; ++o) Add(id(o, i, j), id(o - d, x, y), INF); } printf("%d\n", dinic()); return 0;}

转载于:https://www.cnblogs.com/Qihoo360/p/10499479.html

你可能感兴趣的文章
秒杀多线程第三篇 原子操作 Interlocked系列函数
查看>>
boost之ThreadPool
查看>>
如何打造测试工程师精英团队?
查看>>
Linux(CentOS)下同时启动两个tomcat
查看>>
从B树、B+树、B*树谈到R 树
查看>>
java 转换流 打印流 数据流
查看>>
你知道如何判定一个大整数为素数吗?——米勒拉宾素数判定算法
查看>>
form 元素横向排列
查看>>
webapp 移动端开发
查看>>
php 无限分类
查看>>
Linux 安装配置maven3.0 以及搭建nexus私服
查看>>
Python常用模块小结
查看>>
linux中reboot、shutdown、halt等命令详细讲解
查看>>
FileUtils 文件下载 文件导出
查看>>
.net 索引器
查看>>
第3.2 使用案例1:股票期货stock portfolio 21050917
查看>>
C++动态创建类的实例
查看>>
第三次作业——个人作业——软件产品案例分析
查看>>
面向对象程序设计
查看>>
Java对图片压缩
查看>>