网络流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 个方格的棋盘中,每个方格中有一个正整数.现要从 ...
随机推荐
- C++继承(一) 三种继承方式
继承定义 继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一. 继承就是不修改原有的类,直接利用原来的类的属性和方法并进行扩展.原来的类称为基类,继承的类称为派生类,他们的关系就像父子 ...
- <Android基础> (六) 数据存储 Part 2 SharedPreferences方式
6.3 SharedPreferences存储 SharedPreferences使用键值对的方式来存储数据.同时支持多种不同的数据类型. 6.3.1 将数据存储到SharedPreferences中 ...
- JavaScript速记
JavaScript常见知识点积累,包括数据类型.数值转换.对象.原型与原型链.作用域与闭包等等,持续整理更新,如有错误请指正,甚是感激 本文链接:JavaScript那些磨人的小妖精 作者:狐狸家的 ...
- Spring 实现动态数据源切换--转载 (AbstractRoutingDataSource)的使用
[参考]Spring(AbstractRoutingDataSource)实现动态数据源切换--转载 [参考] 利用Spring的AbstractRoutingDataSource解决多数据源的问题 ...
- 程序人生 | 35岁以上的 iOS 程序员都到哪里去了?
1.网上流传华为公司正在清理 34 岁以上的员工. " 中国区开始集中清理 34 + 的交付员工,...... 去向是跟海外服务部门交换今年新毕业的校招员工,也就是进新人,出旧人. 这些旧人 ...
- 04--STL序列容器(Stack和Queue)
总括: stack和queue不支持迭代 一:栈Stack (一)栈的简介 stack是堆栈容器,是一种“先进后出”的容器. stack是简单地装饰deque容器而成为另外的一种容器. (二)栈的默认 ...
- mac 连接linux服务器,用scp命令实现本地文件与服务器文件之间的互相传输
mac连接linux服务器 打开终端,切换到root权限下,切换root权限命令:sudo -i 通过ssh命令连接linux服务器:ssh root@ip地址(root是账户名) 然后根据提示输入密 ...
- 使用Docker+Jenkins自动构建部署
环境 Windows 10 Docker Version 18.06.1-ce-win73 (19507) 运行jenkins 运行jenkins 容器 docker run -d --name ln ...
- Python编程四大神兽:迭代器、生成器、闭包和装饰器
生成器 生成器是生成一个值的特殊函数,它具有这样一个特点:第一次执行该函数时,先从头按顺序执行,在碰到yield关键字时该函数会暂停执行该函数后续的代码,并且返回一个值:在下一次调用该函数执行时,程序 ...
- xls 打乱序列 -和给拼接字符串加上双引号
打乱 给空列 添加函数 =RAND() ,下拉,排序,即可打乱 添加双引号: =""""&C1&"""" ...