ACdream 1128 Maze(费用流)
题目链接:http://acdream.info/problem?pid=1128
Problem Description
Input
有多组数据。
每组数据第一行是两个正整数N和M(1<=N,M<=100)。
接下来一行两个整数为x和y(1<=x,y<=100)
接下来N行,每行有M个非负整数,第i行的第j个数为p(i,j)(0<=p(i,j)<=20)代表(i,j)格子上有的箱子数。
Output
输出wuyiqi逃离需要消耗的最小RP值。
题目大意:略。
思路:考虑结果的话,每行的总和是一样的,每列的总和是一样的。那么每行的总和是n的倍数,每列的总和是m的倍数。那么整个棋盘的总和一定是lcm(n, m)的倍数。
那么枚举最终棋盘剩余的箱子数,枚举lcm(n, m)的倍数,假设为b,那么需要销毁的箱子数为(sum - b) * y,其中sum为总箱子数。
现在考虑每一行间箱子的移动,设sumr[i]为第 i 行的箱子总和,现在要求每一行都变成b / n。
建图,建一个源点,连一条边到每一行的容量为sumr[i],费用为0。建一个汇点,每一行到汇点连一条边,容量为b / n,费用为0。
相邻的行之间连一条边,容量为正无穷大,费用为x。
跑最小费用最大流可得到箱子在行之间移动的代价。同理可以得到箱子在列之间移动的代价。
取枚举之后的总代价的最小值。
PS:肉眼DEBUG的时候发现以前一直在用的SPFA费用流模板是错的……
代码(96MS):
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <numeric>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXV = ;
const int MAXE = * MAXV;
const int INF = 0x7f7f7f7f; struct SPFA_COST_FLOW {
int head[MAXV];
int to[MAXE], next[MAXE], cost[MAXE], flow[MAXE];
int n, ecnt, st, ed; void init(int nn) {
n = nn;
memset(head + , -, n * sizeof(int));
ecnt = ;
} void add_edge(int u, int v, int c, int w) {
to[ecnt] = v; flow[ecnt] = c; cost[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; cost[ecnt] = -w; next[ecnt] = head[v]; head[v] = ecnt++;
} bool vis[MAXV];
int dis[MAXV], pre[MAXV];
queue<int> que; bool spfa() {
memset(vis + , , n * sizeof(bool));
memset(dis + , 0x7f, n * sizeof(int));
dis[st] = ; que.push(st);
while(!que.empty()) {
int u = que.front(); que.pop();
vis[u] = false;
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(flow[p] && dis[v] > dis[u] + cost[p]) {
dis[v] = dis[u] + cost[p];
pre[v] = p;
if(!vis[v]) {
que.push(v);
vis[v] = true;
}
}
}
}
return dis[ed] < INF;
} int maxFlow, minCost;
int min_cost_flow(int ss, int tt) {
st = ss, ed = tt;
maxFlow = minCost = ;
while(spfa()) {
int u = ed, tmp = INF;
while(u != st) {
tmp = min(tmp, flow[pre[u]]);
u = to[pre[u] ^ ];
}
u = ed;
while(u != st) {
flow[pre[u]] -= tmp;
flow[pre[u] ^ ] += tmp;
u = to[pre[u] ^ ];
}
maxFlow += tmp;
minCost += tmp * dis[ed];
}
return minCost;
}
} G; int mat[MAXN][MAXN];
int sumr[MAXN], sumc[MAXN];
int n, m, x, y; int calc(int sum[], int n, int c) {
int ss = n + , tt = n + ;
G.init(n + );
for(int i = ; i <= n; ++i)
G.add_edge(ss, i, sum[i], ), G.add_edge(i, tt, c, );
for(int i = ; i < n; ++i)
G.add_edge(i, i + , INF, x), G.add_edge(i + , i, INF, x);
return G.min_cost_flow(ss, tt);
} int solve() {
int sum = accumulate(sumr + , sumr + n + , ), ans = sum * y;
int lcm = n * m / __gcd(n, m);
for(int b = lcm; b <= sum; b += lcm) {
ans = min(ans, (sum - b) * y + calc(sumr, n, b / n) + calc(sumc, m, b / m));
}
return ans;
} int main() {
while(scanf("%d%d", &n, &m) != EOF) {
scanf("%d%d", &x, &y);
for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j) scanf("%d", &mat[i][j]);
memset(sumr + , , n * sizeof(int));
memset(sumc + , , m * sizeof(int));
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
sumr[i] += mat[i][j];
sumc[j] += mat[i][j];
}
}
printf("%d\n", solve());
}
}
ACdream 1128 Maze(费用流)的更多相关文章
- hdu-5988 Coding Contest(费用流)
题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...
- POJ2195 Going Home[费用流|二分图最大权匹配]
Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22088 Accepted: 11155 Desc ...
- BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]
3130: [Sdoi2013]费用流 Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 960 Solved: 5 ...
- 洛谷 1004 dp或最大费用流
思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...
- Codeforces 730I [费用流]
/* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给两行n个数,要求从第一行选取a个数,第二行选取b个数使得这些数加起来和最大. 限制条件是第一行选取了某个数的条件下,第二行不能选取对应位置的数. ...
- zkw费用流+当前弧优化
zkw费用流+当前弧优化 var o,v:..] of boolean; f,s,d,dis:..] of longint; next,p,c,w:..] of longint; i,j,k,l,y, ...
- 【BZOJ-4213】贪吃蛇 有上下界的费用流
4213: 贪吃蛇 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 58 Solved: 24[Submit][Status][Discuss] Desc ...
- 【BZOJ-3638&3272&3267&3502】k-Maximum Subsequence Sum 费用流构图 + 线段树手动增广
3638: Cf172 k-Maximum Subsequence Sum Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 174 Solved: 9 ...
- [bzoj4514]数字配对[费用流]
今年SDOI的题,看到他们在做,看到过了一百多个人,然后就被虐惨啦... 果然考试的时候还是打不了高端算法,调了...几天 默默地yy了一个费用流构图: 源连所有点,配对的点连啊,所有点连汇... 后 ...
随机推荐
- CC2540 USB DONGLE 使用 BTool 调试BLE 说明
一.Btool软件界面介绍 首先您要将USBDONGLE插入电脑的USB口,然后打开双击打开Btool软件,打开后如下图所示: 在安装驱动的教程中,我们已经记住了我们的USB DONGLE的串口号,在 ...
- 低功耗蓝牙4.0BLE编程-nrf51822开发(6)-Battery Service
Battery Service是有关电池特性方面的服务,如果需要它,在初始化时将它加入到蓝牙协议栈. 如果通过ble_bas_battery_level_update(),电池电量将会通知,Batte ...
- eclipse dbviewer,eclipse java8
进入/home/xxx(用户名)/.local/share/applications,看是否有eclipse和深度音乐desktop配置文件,为eclipse.desktop配置图标, 那现在终端输入 ...
- JavaScript中关于bool类型判断的一些总结。
我从书上看到了一些关于 int类型 0 转换成boolean值得时候会把0转换成 false ,string 类型 的 "" 也会装换成false; 所以我就想,我能不能用一 ...
- SQL Server数据库连接字符串的组成
DB驱动程序常见的驱动程序如下: ODBC ODBC(Open Database Connectivity,开放数据库互连)是微软公司开放服务结构(WOSA,Windows Open Servic ...
- Windows创建文件链接
Windows平台创建文件.文件夹链接: 测试平台,windows10. D:\>mklink 创建符号链接. MKLINK [[/D] | [/H] | [/J]] Link Target / ...
- Linux Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)
我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web 服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠s ...
- java字符串和unicode互转
直接上代码 private static String decodeUnicode(String input) { if (null == input) return input; int len = ...
- css3 loading效果
file:///E:/zhangqiangWork/2014/SPDbank/index.html 参考该网站 http://tobiasahlin.com/spinkit/ 查看源代码把里面的dom ...
- Emiller's Advanced Topics In Nginx Module Development
Emiller的Nginx模块开发指南 By Evan Miller DRAFT: August 13, 2009 (changes) 翻译:Kongch @2010年1月5日 0:04am -- 2 ...