luogu P4013 数字梯形问题
三倍经验,三个条件,分别对应了常见的3种模型,第一种是限制每个点只能一次且无交点,我们可以把这个点拆成一个出点一个入点,capacity为1,这样就限制了只选择一次,第二种是可以有交点,但不能有交边,那我们就不需要拆点,限制每条capacity都为1就可以了,第三种直接连,没有限制(
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&(-x))
typedef long long LL; const int maxm = 1e6+;
const int INF = 0x3f3f3f3f; struct edge{
int u, v, cap, flow, cost, nex;
} edges[maxm]; int head[maxm], cur[maxm], cnt, fa[maxm], d[maxm], buf[][], num[][], ID;
bool inq[maxm]; void init() {
memset(head, -, sizeof(head));
} void add(int u, int v, int cap, int cost) {
edges[cnt] = edge{u, v, cap, , cost, head[u]};
head[u] = cnt++;
} void addedge(int u, int v, int cap, int cost) {
add(u, v, cap, cost), add(v, u, , -cost);
} bool spfa(int s, int t, int &flow, LL &cost) {
//for(int i = 0; i <= n+1; ++i) d[i] = INF; //init()
memset(d, , sizeof(d));
memset(inq, false, sizeof(inq));
d[s] = , inq[s] = true;
fa[s] = -, cur[s] = INF;
queue<int> q;
q.push(s);
while(!q.empty()) {
int u = q.front();
q.pop();
inq[u] = false;
for(int i = head[u]; i != -; i = edges[i].nex) {
edge& now = edges[i];
int v = now.v;
if(now.cap > now.flow && d[v] > d[u] + now.cost) {
d[v] = d[u] + now.cost;
fa[v] = i;
cur[v] = min(cur[u], now.cap - now.flow);
if(!inq[v]) {q.push(v); inq[v] = true;}
}
}
}
if(d[t] == INF) return false;
flow += cur[t];
cost += 1LL*d[t]*cur[t];
for(int u = t; u != s; u = edges[fa[u]].u) {
edges[fa[u]].flow += cur[t];
edges[fa[u]^].flow -= cur[t];
}
return true;
} int MincostMaxflow(int s, int t, LL &cost) {
cost = ;
int flow = ;
while(spfa(s, t, flow, cost));
return flow;
} void run_case() {
int m, n; cin >> m >> n;
int s = , t = 1e6;
// first
init();
for(int i = m; i < n+m; ++i)
for(int j = ; j <= i; ++j) {
num[i][j] = ++ID;
cin >> buf[i][j];
addedge(ID<<, (ID<<)|, , -buf[i][j]);
}
for(int i = m; i < n+m-; ++i) {
for(int j = ; j <= i; ++j) {
addedge((num[i][j]<<)|, num[i+][j]<<, , );
addedge((num[i][j]<<)|, num[i+][j+]<<, , );
}
}
for(int i = ; i <= m; ++i) addedge(s, num[m][i]<<, , );
for(int i = ; i < n+m; ++i) addedge((num[n+m-][i]<<)|, t, , );
LL cost = ;
MincostMaxflow(s, t, cost);
cout << -cost << "\n";
// second
init();
for(int i = m; i < n+m-; ++i)
for(int j = ; j <= i; ++j) {
addedge(num[i][j], num[i+][j], , -buf[i+][j]);
addedge(num[i][j], num[i+][j+], , -buf[i+][j+]);
}
for(int i = ; i <= m; ++i) addedge(s, num[m][i], , -buf[m][i]);
for(int i = ; i < n+m; ++i) addedge(num[n+m-][i], t, INF, );
cost = , MincostMaxflow(s, t, cost);
cout << -cost << "\n";
// third
init();
for(int i = m; i < n+m-; ++i)
for(int j = ; j <= i; ++j) {
addedge(num[i][j], num[i+][j], INF, -buf[i+][j]);
addedge(num[i][j], num[i+][j+], INF, -buf[i+][j+]);
}
for(int i = ; i <= m; ++i) addedge(s, num[m][i], , -buf[m][i]);
for(int i = ; i < n+m; ++i) addedge(num[n+m-][i], t, INF, );
cost = , MincostMaxflow(s, t, cost);
cout << -cost << "\n";
} int main() {
ios::sync_with_stdio(false), cin.tie();
run_case();
cout.flush();
return ;
}
luogu P4013 数字梯形问题的更多相关文章
- P4013 数字梯形问题 网络流二十四题
P4013 数字梯形问题 题目描述 给定一个由 nn 行数字组成的数字梯形如下图所示. 梯形的第一行有 m 个数字.从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形 ...
- P4013 数字梯形问题 网络流
题目描述 给定一个由 nn 行数字组成的数字梯形如下图所示. 梯形的第一行有 mm 个数字.从梯形的顶部的 mm 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径. 分别 ...
- P4013 数字梯形问题
\(\color{#0066ff}{题目描述}\) 给定一个由 \(n\) 行数字组成的数字梯形如下图所示. 梯形的第一行有 \(m\) 个数字.从梯形的顶部的 \(m\) 个数字开始,在每个数字处可 ...
- 洛谷P4013数字梯形问题——网络流24题
题目:https://www.luogu.org/problemnew/show/P4013 最大费用最大流裸题: 注意:在第二种情况中,底层所有点连向汇点的边容量应该为inf,因为可以有多条路径结束 ...
- 洛谷P4013 数字梯形问题(费用流)
传送门 两个感受:码量感人……大佬nb…… 规则一:$m$条路径都不相交,那么每一个点只能经过一次,那么考虑拆点,把每一个点拆成$A_{i,j}$和$B_{i,j}$,然后两点之间连一条容量$1$,费 ...
- 洛谷P4013 数字梯形问题(费用流)
题意 $N$行的矩阵,第一行有$M$个元素,第$i$行有$M + i - 1$个元素 问在三个规则下怎么取使得权值最大 Sol 我只会第一问qwq.. 因为有数量的限制,考虑拆点建图,把每个点拆为$a ...
- 洛谷 P4013 数字梯形问题【最大费用最大流】
第一问:因为每个点只能经过一次,所以拆点限制流量,建(i,i',1,val[i]),然后s向第一行建(s,i,1,0),表示每个点只能出发一次,然后最后一行连向汇点(i',t,1,0),跑最大费用最大 ...
- 洛谷 P4013 数字梯形问题
->题目链接 题解: 网络流. #include<cstdio> #include<iostream> #include<queue> #include< ...
- 【费用流】【网络流24题】【P4013】 数字梯形问题
Description 给定一个由 \(n\) 行数字组成的数字梯形如下图所示. 梯形的第一行有 \(m\) 个数字.从梯形的顶部的 \(m\) 个数字开始,在每个数字处可以沿左下或右下方向移动,形成 ...
随机推荐
- 1010 Radix
1010 Radix 注意点 如111 1 1 10类似情况下,若n为个位数,如果本身比另一个数小,则多少的进制都是没有用的(可能会造成空循环而超时),不过好像没有这么一个测试用例 进制应该比最少数据 ...
- Python实现mysql数据库增删改查
利用python操作mysql数据库用法简单,环境配置容易,本文将实现对库增.删.改.查的简易封装! 1. 环境配置 安装第三方包 ,导入模块 mysql.connector pip inst ...
- enviroment linux jdk and git and maven
#java_home export JAVA_HOME=/usr/local/java/jdk1.8.0_211 export JRE_HOME=$JAVA_HOME/jre export CLASS ...
- 「HNOI2012」永无乡
传送门 Luogu 解题思路 很容易想到平衡树,然后还可以顺便维护一下连通性,但是如何合并两棵平衡树? 我们采用一种类似于启发式合并的思想,将根节点siz较小的那颗平衡树暴力的合并到另一颗上去. 那么 ...
- 《JavaScript高级程序设计》读书笔记(五)引用类型
内容---使用对象---创建并操作数组---理解基本的JavaScript类型---使用基本类型和基本包装类型 引用类型--引用类型的值(对象)是引用类型的一个实例--在ECMAScript中,引用类 ...
- Python分析盘点2019全球流行音乐:是哪些歌曲榜单占领了我们?
写在前面:圣诞刚过,弥留者节日气息的大家是否还在继续学习呐~在匆忙之际也不忘给自己找几首好听的歌曲放松一下,缠绕着音乐一起来看看关于2019年流行音乐趋势是如何用Python分析的吧! 昨天下午没事儿 ...
- python-opencv:读取图片
代码 import cv2 # 读取一张图片 src = cv2.imread("../images/lena.jpg") # 命名一个窗口 cv2.namedWindow(&qu ...
- python上传文件接口
1.由于公司做接口测试,遇到了上传文件,一直搞了好久,原来是加了头部的原因def test_79(self): '''导入配置文件''' request = e['mysqlshujuku'] url ...
- GO第归
Go 语言递归函数 递归,就是在运行的过程中调用自己. 语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { ...
- XCOJ 1205 A.First Blood
1205: A.First Blood 时间限制: 1 Sec 内存限制: 64 MB提交: 152 解决: 44 标签提交统计讨论版 题目描述 盖伦是个小学一年级的学生,在一次数学课的时候,老师 ...