HIT 2715 - Matrix3 - [最小费用最大流][数组模拟邻接表MCMF模板]
题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2715
Time limit : 5 sec Memory limit : 64 M
Zhouguyue is a "驴友" and nowadays he likes traveling on an N * N matrix with a non-negative number in each grid, and each grid has a height. Zhouguyue starts his matrix travel with POINT = 0. For each travel, zhouguyue can land on any grid he wants with the help of bin3's helicopter, and then he can only move to ajacent grids whose height is less than his current height. Notice that when he is at the side of the matrix, he can also move out of the matrix. After he moves out of the matrix, he completes one travel. He adds the number in each grid he visited to POINT, and replaces it with zero. Now zhouguyue is wondering what is the maximum POINT he can obtain after he travels at most K times. Note the POINT is accumulative during the travels.
Input
The first line is a integer T indicating the number of test cases.T cases fllows. The first line of each case contains two integers N and K (1 ≤ N ≤ 50, 0 ≤ K ≤ 50) described above. The following N lines represents the matrix. You can assume the numbers in the matrix are non-negative integers and no more than 10000. The following N lines represents the height of each grid. The heghts are also non-negative integers.
Output
The maximum POINT zhouguyue can obtain after he travels at most K times.
Sample Input
1
3 2
1 2 3
3 2 1
2 4 2 3 5 3
2 1 0
1 2 3
Sample Output
17
题意:
一个 N*N 的网格,每个单元都有一个数字number[i][j],和一个高度height[i][j]。
现在 ZhouGuyue 要作至多 K 次旅行,每次旅行如下:
他可以借助 bin3 的直升机飞到 任意一个单元格,之后他每次只能向相邻的且高度比当前所在格子低的格子移动。
当他移动到一个边界的格子上时,他可以跳出这个网格并完成一次旅行。
旅行开始前,他有一个POINT,初始值为0;旅行途中,所到的每一格的number[i][j]可以加到他的POINT里,一旦加上,格子里number[i][j]就变成0。
问POINT最大有多大。(1 <= N <= 50, 0 <= K <= 50, 0 <= Vi <= 10000)
解题思路:
本题属于最大费用最大流问题,对cost取负后转变成为最小费用最大流问题,构图完成后可以直接上模板,最后求出mincost再取个负即为答案。
构图:
将每个格子 i 进行拆点,并加边(i’, i’’, 1, -number[i]), (i’, i’’, ∞, 0), (s, i’, ∞, 0);(分别对应from,to,cap,cost)
这代表,他走第一次,可以走(i’, i’’, 1, -number[i]),由于算法保证最小费用,他也只会先走(i’, i’’, 1, -number[i]);
走过这个格子,可以得到number,然后后面虽然可以继续走这个格子,但只能通过(i’, i’’, ∞, 0)这条边走,就得不到number;
另外,由于他可以从任意格子出发,故要建立超级源点s,连接每个格子。
对相邻的四个格子 j,若 Hi > Hj 则加边(i’’, j’, ∞, 0);
这条边很简单,代表可以同行,并且想走多少次都可以。
若格子 i在边界上则加边(i’’, t, ∞, 0);
代表走到边界,可以直接结束本次旅行,由于边界上有许多格子,故也要建立超级汇点。
限制增广次数小于等于 K 。
有增广一次可以看做沿某个路线走了一遍,并且获得了沿途的每个格子的number,增广次数不超过K,即代表旅行次数最多为K。
注意要点:
HIT的OJ可能卡STL,使用vector做邻接表超时(然后就只好自己写数组模拟邻接表呗,不过改一下也挺快,没啥问题);
如果使用的是刘汝佳书上的MCMF模板,while(spfa())语句增加限制次数K要注意写法,我就是没考虑到K==0的情况,刚开始写挫了,WA了一发;
代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define MAXN 2*53*53
#define MAXM 8*MAXN
#define INF 0x3f3f3f3f
#define in(x) x
#define out(x) x+n
using namespace std;
int n,N,K;
struct Edge{
int u,v,c,f,a;
};
struct MCMF
{
int s,t,ne;
Edge E[MAXM];
int head[MAXN],next[MAXM];
int vis[MAXN];
int d[MAXN];
int pre[MAXN];
int aug[MAXN];
void init()
{
ne=;
memset(head,-,sizeof(head));
}
void addedge(int from,int to,int cap,int cost)
{
E[ne].u=from, E[ne].v=to, E[ne].c=cap, E[ne].f=, E[ne].a=cost;
next[ne]=head[from]; head[from]=ne++;
E[ne].u=to, E[ne].v=from, E[ne].c=, E[ne].f=, E[ne].a=-cost;
next[ne]=head[to]; head[to]=ne++;
}
bool SPFA(int s,int t,int &flow,int &cost)
{
memset(d,INF,sizeof(d));
memset(vis,,sizeof(vis));
d[s]=, vis[s]=, pre[s]=, aug[s]=INF;
queue<int> q;
q.push(s);
while(!q.empty())
{
int now=q.front(); q.pop();
vis[now]=;
for(int i=head[now];i!=-;i=next[i])
{
Edge& e=E[i];
int nex=e.v;
if(e.c>e.f && d[nex]>d[now]+e.a)
{
d[nex]=d[now]+e.a;
pre[nex]=i;
aug[nex]=min(aug[now],e.c-e.f);
if(!vis[nex])
{
q.push(nex);
vis[nex]=;
}
}
}
}
if(d[t]==INF) return ;
flow+=aug[t];
cost+=d[t]*aug[t];
for(int i=t;i!=s;i=E[pre[i]].u)
{
E[pre[i]].f+=aug[t];
E[pre[i]^].f-=aug[t];
}
return ;
}
int mincost()
{
int flow=,cost=,cnt=;
while(cnt<K && SPFA(s,t,flow,cost)) cnt++;
return cost;
}
}mcmf; int number[][],height[][];
int d[][]={{,},{,},{,-},{-,}};
int inmap(int i,int j)
{
if(<=i && i<=N && <=j && j<=N) return (i-)*N+j;
else return ;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&N,&K);
for(int i=;i<=N;i++) for(int j=;j<=N;j++) scanf("%d",&number[i][j]);
for(int i=;i<=N;i++) for(int j=;j<=N;j++) scanf("%d",&height[i][j]);
n=N*N;
mcmf.init();
mcmf.s=, mcmf.t=*n+;
for(int i=;i<=N;i++)
{
for(int j=;j<=N;j++)
{
int id=(i-)*N+j;
mcmf.addedge(mcmf.s,in(id),INF,);
mcmf.addedge(in(id),out(id),,-number[i][j]);
mcmf.addedge(in(id),out(id),INF,);
if(i== || i==N || j== || j==N) mcmf.addedge(out(id),mcmf.t,INF,);
for(int k=;k<;k++)
{
int nex_i=i+d[k][], nex_j=j+d[k][],nex_id;
if((nex_id=inmap(nex_i,nex_j)) && height[i][j]>height[nex_i][nex_j]) mcmf.addedge(out(id),in(nex_id),INF,);
}
}
}
printf("%d\n",-mcmf.mincost());
}
}
HIT 2715 - Matrix3 - [最小费用最大流][数组模拟邻接表MCMF模板]的更多相关文章
- 最小费用最大流 学习笔记&&Luogu P3381 【模板】最小费用最大流
题目描述 给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 题目链接 思路 最大流是没有问题的,关键是同时保证最小费用,因此,就可以把 ...
- SDUT OJ 图练习-BFS-从起点到目标点的最短步数 (vector二维数组模拟邻接表+bfs , *【模板】 )
图练习-BFS-从起点到目标点的最短步数 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 在古老的魔兽传说中,有两个军团,一个叫天 ...
- HIT 2739 - The Chinese Postman Problem - [带权有向图上的中国邮路问题][最小费用最大流]
题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2739 Time limit : 1 sec Memory limit : 64 M A Chinese ...
- 【BZOJ】1221: [HNOI2001] 软件开发(最小费用最大流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1221 先吐槽一下,数组依旧开小了RE:在spfa中用了memset和<queue>的版本 ...
- 最小费用最大流 POJ2195-Going Home
网络流相关知识参考: http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591573.html 出处:優YoU http://blog.csdn. ...
- hdu-3376-Matrix Again(最小费用最大流)
题意: 给一个矩形,从左上角走到右下角,并返回左上角(一个单元格只能走一次,左上角和右下角两个点除外) 并且从左上到右下只能往右和下两个方向.从右下返回左上只能走上和左两个方向! 分析: 拆点,最小费 ...
- Luogu P3381 (模板题) 最小费用最大流
<题目链接> 题目大意: 给定一张图,给定条边的容量和单位流量费用,并且给定源点和汇点.问你从源点到汇点的最带流和在流量最大的情况下的最小费用. 解题分析: 最小费用最大流果题. 下面的是 ...
- 经典贪心算法(哈夫曼算法,Dijstra单源最短路径算法,最小费用最大流)
哈夫曼编码与哈夫曼算法 哈弗曼编码的目的是,如何用更短的bit来编码数据. 通过变长编码压缩编码长度.我们知道普通的编码都是定长的,比如常用的ASCII编码,每个字符都是8个bit.但在很多情况下,数 ...
- [BZOJ2055]80人环游世界 有上下界最小费用最大流
2055: 80人环游世界 Time Limit: 10 Sec Memory Limit: 64 MB Description 想必大家都看过成龙大哥的<80天环游世界>,里面 ...
随机推荐
- ios开发之--CGRectGetXxx方法图解 和代码NSLog输出值
- (void)test { CGRect rect = CGRectMake(, , , ); // 最小Y坐标,即矩形的顶部top y坐标: minY = rect.y = 20.000000 N ...
- 安装centos6.5
我是在虚拟机上面安装的centos6.5,本机的系统是windows 2008 datacenter. 到这个地方下载镜像文件:http://mirrors.sohu.com/centos/6.5/i ...
- LR 测试http协议xml格式数据接口
Action() { lr_start_transaction("T1"); web_custom_request("xxxxHTTPRequest", &qu ...
- Oracle查询锁表和解锁
1.查询是否锁表 SELECT l.session_id sid, s.serial#, l.locked_mode,l.oracle_username, l.os_user_name,s.machi ...
- Streaming 101
开宗明义!本文根据Google Beam大神Tyler Akidau的系列文章<The world beyond batch: Streaming 101>(批处理之外的流式世界)整理而成 ...
- IDEA 单元测试 导入JUnit4到项目
一.IDEA自带JUnit4的jar包,现在让我们来导入. Step 1. IDEA最上面一栏的菜单栏中,选File->Project Structure(从上往下第11个),弹出窗口左边有一个 ...
- 从Eclipse转移到IntelliJ IDEA的一点心得
IntelliJ使用指南—— 深入理解IntelliJ的Web部署逻辑 Intellij IDEA 部署Web项目,解决 404 错误 Intellij IDEA快捷键的使用 本文转载地址 本人使用I ...
- spring applicationContext.xml 配置文件 详解
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://ww ...
- android cannot locate symbol 'sigemptyset'问题解决
设备是android 4.1的平板电脑,支持armeabi-v7a和mips,为了能用上poco c++ lib,用cmake编译了poco mips架构的lib,但在android studio里引 ...
- 常用的数据整理的JavaScript库
Lodash.js https://lodash.com/ Underscore.js https://www.html.cn/doc/underscore/