网络流24题——数字梯形问题 luogu 4013
题目描述:这里
极其裸的一道费用流问题
首先分析第一问,由于要求一个点只能经过一次,所以我们将梯形中的每一个点拆成两个点(记为入点和出点,顾名思义,入点用来承接上一行向这一行的边,出点用来向下一行连边)
然后将出入点之间的流量设为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的更多相关文章
- COGS738 [网络流24题] 数字梯形(最小费用最大流)
题目这么说: 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径.规则1:从梯形的 ...
- Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算)
Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算) Description T 公司发现其研制的一个软件中有 n 个错误,随即为该软件发放 ...
- Libre 6006 「网络流 24 题」试题库 / Luogu 2763 试题库问题 (网络流,最大流)
Libre 6006 「网络流 24 题」试题库 / Luogu 2763 试题库问题 (网络流,最大流) Description 问题描述: 假设一个试题库中有n道试题.每道试题都标明了所属类别.同 ...
- 网络流24题——魔术球问题 luogu 2765
题目描述:这里 这道题是网络流问题中第一个难点,也是一个很重要的问题 如果直接建图感觉无从下手,因为如果不知道放几个球我就无法得知该如何建图(这是很显然的,比如我知道 $1+48=49=7^2$ ,可 ...
- 网络流24题——试题库问题 luogu 2763
题目描述看:这里 这是我们遇到的第一个要求输出方案的问题 考虑建图然后用最大流思想: 首先由源点向每一道试题连边,容量为1 然后由每一种试题类型向汇点连边,容量为需求量 最后由每一道试题向可能属于的试 ...
- 网络流24题——骑士共存问题 luogu 3355
题目描述:这里 从这里开始,我们涉及到了一个新的问题:最小割问题 首先给出一些定义(本人根据定义自己口胡的): 一个流网络中的一个割是一个边集,使得割掉这些边集后源点与汇点不连通 而最小割问题就是一个 ...
- Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)
Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...
- LOJ #6010. 「网络流 24 题」数字梯形
#6010. 「网络流 24 题」数字梯形 题目描述 给定一个由 n nn 行数字组成的数字梯形如下图所示.梯形的第一行有 m mm 个数字.从梯形的顶部的 m mm 个数字开始,在每个数字处可以 ...
- Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流)
Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流) Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从 ...
随机推荐
- [转载] .NET 中可以有类似 JVM 的幻像引用吗?
近日发现一篇不错的文章,文中列举了一些 GC 场景,探讨了 在 .NET 中是需要实现像 JVM 的中的幻像引用.有人质疑其不切实际,也有像 Ayende 大神一言不合就自己做了个 demo. Do ...
- ubuntu14.04按照mysql5.7
1.安装mysql5.5 https://www.cnblogs.com/zhuyp1015/p/3561470.html https://www.cnblogs.com/ruofengzhishan ...
- htaccess 的使用基本小节 For apache httpd
htaccess 的使用基本小节 For apache httpd .htaccess的基本作用 .htaccess是一个纯文本文件,它里面存放着Apache服务器配置相关的指令. .ht ...
- IntelliJ IDEA 创建 Maven简单项目
创建简单Maven项目 使用IDEA提供的Maven工具,根据artifact创建简单Maven项目.根据下图操作,创建Maven项目. 使用IDEA提供的Maven工具创建的Maven简单项目目录结 ...
- jQuery与原生JS相互转化
前端发展很快,现代浏览器原生 API 已经足够好用.我们并不需要为了操作 DOM.Event 等再学习一下 jQuery 的 API.同时由于 React.Angular.Vue 等框架的流行,直接操 ...
- 当PsychicBoom_发觉自己是个大SB的时候……
这些题都是没ac调了好久发现是sb错误的题--. 想清楚再写题!!! 2019.4.18 洛谷P5155 [USACO18DEC]Balance Beam 转移方程\((a[l[i]]*(r[i]-i ...
- (二叉树 递归) leetcode 889. Construct Binary Tree from Preorder and Postorder Traversal
Return any binary tree that matches the given preorder and postorder traversals. Values in the trave ...
- 二、docker的安装和基本命令
一.docker的安装 1.安装依赖 # yum install -y yum-utils device-mapper-persistent-data 2.设置yum源 # yum-config-ma ...
- \t \r \n \f
\t 的意思是 :水平制表符.将当前位置移到下一个tab位置. \r 的意思是: 回车.将当前位置移到本行的开头. \n 的意思是:回车换行.将当前位置移到下一行的开头. \f的意思是:换页.将当前位 ...
- Vue学习笔记一:初识Vue
目录 什么是Vue? 为什么要学习前端框架? MVC,MVP 和 MVVM 最简单的入门小案例 下载Vue.js 新建文件结构 写一个html 运行 可笑的小报错 Vue和MVVM 什么是Vue? V ...