题目描述:这里

极其裸的一道费用流问题

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

然后将出入点之间的流量设为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. leanote使用本地账户时,去掉待同步的小红点

    切换开发者工具,如下图,点击左上角的箭头图标,选取元素,直接选择小红点. 然后会看到小红点来自于resources/app/public/themes/default.css文件中2092行: .it ...

  2. ES6中的Array.from()函数的用法

    ES6为Array增加了from函数用来将其他对象转换成数组. 当然,其他对象也是有要求,也不是所有的,可以将两种对象转换成数组. 1.部署了Iterator(迭代器)接口的对象,比如:Set,Map ...

  3. Mybatis技术原理理——整体流程理解

    前言:2018年,是最杂乱的一年!所以你看我的博客,是不是很空! 网上有很多关于Mybatis原理介绍的博文,这里介绍两篇我个人很推荐的博文 Mybatis3.4.x技术内幕和 MyBaits源码分析 ...

  4. 【莫烦Pytorch】【P1】人工神经网络VS. 生物神经网络

    滴:转载引用请注明哦[握爪] https://www.cnblogs.com/zyrb/p/9700343.html 莫烦教程是一个免费的机器学习(不限于)的学习教程,幽默风俗的语言让我们这些刚刚起步 ...

  5. eclipse安装cucumber插件

    help-install new software-add name= c location= http://cucumber.github.com/cucumber-eclipse/update-s ...

  6. jmeter 多个sql写在一个jdbc请求中注意事项

    在url里面加上?allowMultiQueries=true 类型选callableStatement

  7. arcgis图层 GraphicsLayer与FeatureLayer

    什么是图层 图层是用来在 ArcGIS 产品套件中显示地理数据集的机制.每个图层代表一种数据集(可以是地图服务.图形或是矢量数据),并指定该数据集是如何描绘使用一组属性的. 包含一个地图控件的每个应用 ...

  8. CTR预估中GBDT与LR融合方案(转载)

    1.背景 CTR预估,广告点击率(Click-Through Rate Prediction)是互联网计算广告中的关键环节,预估准确性直接影响公司广告收入.CTR预估中用的最多的模型是LR(Logis ...

  9. python-类对象以字典模式操作

    #类对象以字典模式操作 class Person: def __init__(self): self.cache={} def __setitem__(self, key, value): #增加或修 ...

  10. 手把手编写PHP MVC框架实例教程

    源地址:https://www.awaimai.com/128.html#comment-27466 这个不错,用php实现mvc最核心功能,代码量只有几十K. 其实,不管用那种方法,最终都是incl ...