题目描述:这里

极其裸的一道费用流问题

首先分析第一问,由于要求一个点只能经过一次,所以我们将梯形中的每一个点拆成两个点(记为入点和出点,顾名思义,入点用来承接上一行向这一行的边,出点用来向下一行连边)

然后将出入点之间的流量设为1,边权设为0,这样就有效保证了一个点只经过一次

接下来,我们从上一行的出点向下一行的入点连边,容量为1,费用为下一行对应点的代价的相反数,然后建起超级源点与超级终点,分别向第一行的入点连边,容量1费用0,由最后一行出点向终点连边,容量1费用0,跑一遍费用流即可(就是套路的最大费用流)

然后看第二问,发现点可以重复经过,这样就不用拆点了,但边不能重复走,所以我们不拆点,剩下的建边与上面相同

但是注意:两条路径可以相交于最后一行,这样的话如果最后一行的点向汇点连边的容量为1是不够的,所以设的容量要大于等于2

第三问就是把除了源点到第一行的边以外的边边权全改为正无穷即可

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
using namespace std;
const ll inf=0x3f3f3f3f3f3f3f3fll;
struct Edge
{
int next;
int to;
ll val;
ll pri;
}edge[];
int head[];
int nnum[][];
ll a[][];
ll dis[];
int pre[];
int fa[];
ll lim[];
bool used[];
int cnt=;
int tot=;
int st,ed;
int n,m;
void init()
{
memset(edge,,sizeof(edge));
memset(head,-,sizeof(head));
cnt=;
}
void add(int l,int r,ll w,ll v)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
edge[cnt].pri=v;
head[l]=cnt++;
}
int ide(int x)
{
return (x&)?x+:x-;
}
bool spfa()
{
memset(dis,0x3f,sizeof(dis));
memset(lim,,sizeof(lim));
memset(used,,sizeof(used));
used[st]=;
lim[st]=inf;
dis[st]=;
pre[ed]=-;
queue <int> M;
M.push(st);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i!=-;i=edge[i].next)
{
int to=edge[i].to;
if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
{
dis[to]=dis[u]+edge[i].pri;
lim[to]=min(lim[u],edge[i].val);
pre[to]=i,fa[to]=u;
if(!used[to])used[to]=,M.push(to);
}
}
used[u]=;
}
return pre[ed]!=-;
}
ll EK()
{
ll maxw=,minv=;
while(spfa())
{
maxw+=lim[ed];
minv+=dis[ed]*lim[ed];
int temp=ed;
while(temp!=st)
{
edge[pre[temp]].val-=lim[ed];
edge[ide(pre[temp])].val+=lim[ed];
temp=fa[temp];
}
}
return minv;
}
int main()
{
scanf("%d%d",&m,&n);
init();
st=,ed=;
for(int i=;i<=n;i++)
{
for(int j=;j<=m+i-;j++)
{
scanf("%lld",&a[i][j]);
nnum[i][j]=++tot;
}
}
for(int i=;i<=n;i++)
{
for(int j=;j<=m+i-;j++)
{
add(nnum[i][j]<<,(nnum[i][j]<<)|,,-a[i][j]);
add((nnum[i][j]<<)|,nnum[i][j]<<,,a[i][j]);
if(i==)
{
add(st,nnum[i][j]<<,,);
add(nnum[i][j]<<,st,,);
}
if(i==n)
{
add((nnum[i][j]<<)|,ed,,);
add(ed,(nnum[i][j]<<)|,,);
}else
{
add((nnum[i][j]<<)|,(nnum[i+][j]<<),,);
add((nnum[i+][j]<<),(nnum[i][j]<<)|,,);
add((nnum[i][j]<<)|,(nnum[i+][j+]<<),,);
add((nnum[i+][j+]<<),(nnum[i][j]<<)|,,);
}
}
}
printf("%lld\n",-EK());
init();
for(int i=;i<=n;i++)
{
for(int j=;j<=m+i-;j++)
{
if(i==)
{
add(st,nnum[i][j]+,,-a[i][j]);
add(nnum[i][j]+,st,,a[i][j]);
}
if(i==n)
{
add(nnum[i][j]+,ed,,);
add(ed,nnum[i][j]+,,);
}else
{
add(nnum[i][j]+,nnum[i+][j]+,,-a[i+][j]);
add(nnum[i+][j]+,nnum[i][j]+,,a[i+][j]);
add(nnum[i][j]+,nnum[i+][j+]+,,-a[i+][j+]);
add(nnum[i+][j+]+,nnum[i][j]+,,a[i+][j+]);
}
}
}
printf("%lld\n",-EK());
init();
for(int i=;i<=n;i++)
{
for(int j=;j<=m+i-;j++)
{
if(i==)
{
add(st,nnum[i][j]+,,-a[i][j]);
add(nnum[i][j]+,st,,a[i][j]);
}
if(i==n)
{
add(nnum[i][j]+,ed,inf,);
add(ed,nnum[i][j]+,,);
}else
{
add(nnum[i][j]+,nnum[i+][j]+,inf,-a[i+][j]);
add(nnum[i+][j]+,nnum[i][j]+,,a[i+][j]);
add(nnum[i][j]+,nnum[i+][j+]+,inf,-a[i+][j+]);
add(nnum[i+][j+]+,nnum[i][j]+,,a[i+][j+]);
}
}
}
printf("%lld\n",-EK());
return ;
}

网络流24题——数字梯形问题 luogu 4013的更多相关文章

  1. COGS738 [网络流24题] 数字梯形(最小费用最大流)

    题目这么说: 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径.规则1:从梯形的 ...

  2. Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算)

    Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算) Description T 公司发现其研制的一个软件中有 n 个错误,随即为该软件发放 ...

  3. Libre 6006 「网络流 24 题」试题库 / Luogu 2763 试题库问题 (网络流,最大流)

    Libre 6006 「网络流 24 题」试题库 / Luogu 2763 试题库问题 (网络流,最大流) Description 问题描述: 假设一个试题库中有n道试题.每道试题都标明了所属类别.同 ...

  4. 网络流24题——魔术球问题 luogu 2765

    题目描述:这里 这道题是网络流问题中第一个难点,也是一个很重要的问题 如果直接建图感觉无从下手,因为如果不知道放几个球我就无法得知该如何建图(这是很显然的,比如我知道 $1+48=49=7^2$ ,可 ...

  5. 网络流24题——试题库问题 luogu 2763

    题目描述看:这里 这是我们遇到的第一个要求输出方案的问题 考虑建图然后用最大流思想: 首先由源点向每一道试题连边,容量为1 然后由每一种试题类型向汇点连边,容量为需求量 最后由每一道试题向可能属于的试 ...

  6. 网络流24题——骑士共存问题 luogu 3355

    题目描述:这里 从这里开始,我们涉及到了一个新的问题:最小割问题 首先给出一些定义(本人根据定义自己口胡的): 一个流网络中的一个割是一个边集,使得割掉这些边集后源点与汇点不连通 而最小割问题就是一个 ...

  7. Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)

    Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...

  8. LOJ #6010. 「网络流 24 题」数字梯形

    #6010. 「网络流 24 题」数字梯形   题目描述 给定一个由 n nn 行数字组成的数字梯形如下图所示.梯形的第一行有 m mm 个数字.从梯形的顶部的 m mm 个数字开始,在每个数字处可以 ...

  9. Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流)

    Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流) Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从 ...

随机推荐

  1. IFE第一天

    我也不知道自己到底能坚持多少天,希望66天可以坚持下来,flag在此. 第一天的知识大概就是了解一些基本概念. Web: 基于HTTP协议,利用浏览器访问网站. HTML 大概就是告诉浏览器我有一个什 ...

  2. BUGKU Misc 普通的二维码

    下载的文件是一个bmp文件,在我的印象中bmp好像没有什么隐写技巧,有些慌张. 既然是二维码,那不妨先扫一下试一试 哈哈!就不告诉你flag在这里! 嗯,意料之中 1首先我把它放到了stegosolv ...

  3. struts2 --xml配置

    struts2.5 官方文档介绍 这个是struts2.5给出的web.xml配置方式,核心包已经被挪到了ng的上一层 <web-app id="MyStrutsApp" v ...

  4. CBV源码分析

    1 在views中写一个类,继承View,里面写get方法,post方法 2 在路由中配置: url(r'^test/', views.Test.as_view()),实际上第二个参数位置,放的还是一 ...

  5. Python3 找不到库

    import sys sys.path.append('/usr/local/lib64/python3.6/site-packages')sys.path.append('/usr/local/li ...

  6. 树莓派中QT实现I2C

    树莓派中QT实现I2C 在QT中实现 I2C 使用的驱动为 wiringPi 库的引入 LIBS += -lwiringPi LIBS += -lwiringPiDev 代码实现 widget.h 中 ...

  7. js中获取时间new date()的用法

    获取时间: var myDate = new Date();//获取系统当前时间 获取特定格式的时间: myDate.getYear(); //获取当前年份(2位) myDate.getFullYea ...

  8. consul实现分布式锁

    分布式一致性问题: 分布式的CAP理论告诉我们"任何一个分布式系统都无法同时满足一致性(Consistency).可用性(Availability)和分区容错性(Partition tole ...

  9. python8--文件操作 with。。。open语法

    复习   一.类型转换 1.数字类型:int() | bool() | float()  2.str与int:int('10') | int('-10') | int('0') | float('-. ...

  10. layui模板引擎

    <在模板中调用js方法> 1.js代码 layui.define(['laytpl', 'jquery'], function (exports) { var $ = layui.jque ...