题目描述:这里

极其裸的一道费用流问题

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

然后将出入点之间的流量设为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. JumpServer1.0 服务搭建

    JumpServer1.0 服务搭建 系统环境配置 setenforce 0 systemctl stop iptables.service systemctl stop firewalld.serv ...

  2. luogu4166 最大土地面积 (旋转卡壳)

    首先这样的点一定在凸包上 然后旋转卡壳就可以 具体来说,枚举对角线的一个端点,另一个端点在凸包上转,剩下两个点就是一个叉积最大一个最小,而这两个点也是跟着转的 所以是$O(N^2)$ #include ...

  3. 题解:LOJ540游戏

    题目描述 小L计划进行n场游戏,每场游戏使用一张地图,小 L 会同时使用三辆车在该地图上完成游戏. 小 L 的赛车有三辆,分别用大写字母 A.B.C 表示.地图是一张无向简单图(没有重边或自环),每次 ...

  4. 第二周java学习总结

    学号 20175206 <Java程序设计>第二周学习总结 教材学习内容总结 第二章是基本数据类型与数组,第三章是运算符.表达式和语句的内容.如果说第一章是让我们了解JAVA,那么第二章和 ...

  5. TF Multi-GPU single input queue

    多GPU的数据训练,feed images, labels = cifar10.distorted_inputs() split_images = tf.split(images, FLAGS.num ...

  6. Dynamics CRM 如何修复 Access Is Denied - ObjectTypeCode: 2500 的错误

    最近被 Dynamics CRM 的权限配置问题恶心了一个星期,老是报“Access Is Denied”,几经波折,最后终于找到一个比较合适的解决方案,写个博客 mark 下来,方便以后查看. 首先 ...

  7. [Android] Android 手机下 仿 微信 客户端 界面 -- 微聊

    Android 手机下 仿 微信 客户端 界面 -- 微聊 (包括聊天列表 + 聊天对话页 + 朋友圈列表页 + 我的/发现 列表页) 项目演示: 功能说明: 1)底部标签切换 (TabHost + ...

  8. request redirection

    # encoding:utf-8 import reimport jsonimport randomfrom esdapi.config import BASE_URLfrom requests.se ...

  9. 移动文件(git mv)

    使用git mv命令将mian.c移动为main2.c $ git mv main.c main2.c D:\Git\test (master -> origin) $ git status O ...

  10. vue-router.esm.js:1905 TypeError: Cannot convert undefined or null to object

    环境:vue+vuex+element 报错原因 ...mapState('isDialNumber') mapState如果传递一个参数,参数必须是数组 ...mapState(['isDialNu ...