题目链接: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模板]的更多相关文章

  1. 最小费用最大流 学习笔记&&Luogu P3381 【模板】最小费用最大流

    题目描述 给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 题目链接 思路 最大流是没有问题的,关键是同时保证最小费用,因此,就可以把 ...

  2. SDUT OJ 图练习-BFS-从起点到目标点的最短步数 (vector二维数组模拟邻接表+bfs , *【模板】 )

    图练习-BFS-从起点到目标点的最短步数 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 在古老的魔兽传说中,有两个军团,一个叫天 ...

  3. 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 ...

  4. 【BZOJ】1221: [HNOI2001] 软件开发(最小费用最大流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1221 先吐槽一下,数组依旧开小了RE:在spfa中用了memset和<queue>的版本 ...

  5. 最小费用最大流 POJ2195-Going Home

    网络流相关知识参考: http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591573.html 出处:優YoU http://blog.csdn. ...

  6. hdu-3376-Matrix Again(最小费用最大流)

    题意: 给一个矩形,从左上角走到右下角,并返回左上角(一个单元格只能走一次,左上角和右下角两个点除外) 并且从左上到右下只能往右和下两个方向.从右下返回左上只能走上和左两个方向! 分析: 拆点,最小费 ...

  7. Luogu P3381 (模板题) 最小费用最大流

    <题目链接> 题目大意: 给定一张图,给定条边的容量和单位流量费用,并且给定源点和汇点.问你从源点到汇点的最带流和在流量最大的情况下的最小费用. 解题分析: 最小费用最大流果题. 下面的是 ...

  8. 经典贪心算法(哈夫曼算法,Dijstra单源最短路径算法,最小费用最大流)

    哈夫曼编码与哈夫曼算法 哈弗曼编码的目的是,如何用更短的bit来编码数据. 通过变长编码压缩编码长度.我们知道普通的编码都是定长的,比如常用的ASCII编码,每个字符都是8个bit.但在很多情况下,数 ...

  9. [BZOJ2055]80人环游世界 有上下界最小费用最大流

    2055: 80人环游世界 Time Limit: 10 Sec  Memory Limit: 64 MB Description     想必大家都看过成龙大哥的<80天环游世界>,里面 ...

随机推荐

  1. 5 -- Hibernate的基本用法 --1 4 Hibernate概述

    Hibernate 不仅仅管理Java类到数据库的映射(包括Java数据类型到SQL数据类型的映射),还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL和JDBC处理数据的时间.

  2. HDOJ 4276 The Ghost Blows Light(树形DP)

    Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The tomb consists of N room ...

  3. 【代码审计】711cms_V1.0.5前台XSS跨站脚本漏洞分析

      0x00 环境准备 711CMS官网: https://www.711cms.com/ 网站源码版本:711CMS 1.0.5 正式版(发布时间:2018-01-20) 程序源码下载:https: ...

  4. windows防火墙设置端口开放技巧

    选择“打开或者关闭windows防火墙”把防火墙打开,然后选择“高级设置”,选择“创建规则”来指定端口.(这里也可以在“入站规则”里选择已经存在的端口.) 指定ip开放3389端口 某新服务器,开放8 ...

  5. 使用tinyproxy搭建http代理

    一.前言   二.搭建环境 * Linux laptop 2.6.32-45-generic #100-Ubuntu SMP Wed Nov 14 10:41:11 UTC 2012 i686 GNU ...

  6. [JS] console.time() - 计时器构造函数及如何计时

    概述 使用计时器可以对代码运行过程进行测速.你可以给每个计时器取一个名字,每个页面上最多可以运行一万个计时器.当你使用计时器名字调用 console.timeEnd() 函数时,浏览器会返回一个毫秒值 ...

  7. 【cs229-Lecture7】支持向量机(SVM)

    SVM不错的学习资料: 百度网盘链接: http://pan.baidu.com/s/1hqw0Rnm 密码: asec blog:http://www.blogjava.net/zhenandaci ...

  8. Linux下grep命令查找带有tab(退格)的字符

    需要在日志文件统计删除的主帖,而日志文件是tab(退格)字符隔开的:假设日志文件名叫delete.log. 保存格式和保存的数据如下, 删除日期            帖子类型(11为主帖,12为回帖 ...

  9. Windows平台下PHP7添加Sqlserver扩展

    1.7.0.x 7.0.x的扩展下载地址: Microsoft Drivers for PHP for SQL Server  https://www.microsoft.com/en-us/down ...

  10. 异构GoldenGate 12c 双向复制配置

    1.配置window,添加checkpoint表(本文windows和linux互为source和target) GGSCI (WIN-GM5PVS1CILH) 1> view param ./ ...