洛谷P4013 数字梯形问题(费用流)
题意
$N$行的矩阵,第一行有$M$个元素,第$i$行有$M + i - 1$个元素
问在三个规则下怎么取使得权值最大
Sol
我只会第一问qwq。。
因为有数量的限制,考虑拆点建图,把每个点拆为$a_1$和$b_1$,两点之间连流量为$1$,费用为权值的边
从$b_i$向下方和右下的$a_1$连一条流量为$1$,费用为$0$边
从$S$向第一层的$a_1$连流量为$1$,费用为$0$的边,从$b_N$到$T$连流量为$1$,费用为$0$的边
对于第二问,因为没有点的个数的限制,那么就不用拆点了,直接向能到达的点连流量为$1$,费用为点权的边
对于第三问,直接把第二问中的所有边为流量设为$INF$(除了从$S$出发的)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = 1e5 + , INF = 1e9 + ;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = ; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
int N, M, S = , T = 1e5 + ;
int a[][];
struct Edge {
int u, v, w, f, nxt;
}E[MAXN];
int head[MAXN << ], num = ;
inline void add_edge(int x, int y, int w, int f) { E[num] = (Edge){x, y, w, f, head[x]};
head[x] = num++;
}
inline void AddEdge(int x, int y, int w, int f) {
add_edge(x, y, w, f);
add_edge(y, x, -w, );
}
int anscost, dis[MAXN], vis[MAXN], Pre[MAXN];
bool SPFA() {
memset(dis, -0x3f, sizeof(dis));
memset(vis, , sizeof(vis));
queue<int> q; q.push(S); dis[S] = ;
while(!q.empty()) {
int p = q.front(); q.pop(); vis[p] = ;
for(int i = head[p]; i !=- ; i = E[i].nxt) {
int to = E[i].v;
if((dis[to] < dis[p] + E[i].w) && E[i].f > ) {
dis[to] = dis[p] + E[i].w;
Pre[to] = i;
if(!vis[to]) q.push(to), vis[to] = ;
}
}
}
return dis[T] > ;
}
int F() {
int nowflow = INF;
for(int i = T; i != S; i = E[Pre[i]].u) nowflow = min(nowflow, E[Pre[i]].f);
for(int i = T; i != S; i = E[Pre[i]].u) E[Pre[i]].f -= nowflow, E[Pre[i] ^ ].f += nowflow;
anscost += dis[T] * nowflow;
}
int MCMF() {
anscost = ;
while(SPFA())
F();
return anscost;
}
int be[][], tot = , X;
void Solve1() {
memset(head, -, sizeof(head)); num = ;
for(int i = ; i < N; i++) {
for(int j = ; j <= M + i - ; j++) {
AddEdge(be[i][j], be[i][j] + X, a[i][j], );
AddEdge(be[i][j] + X, be[i + ][j], , );
AddEdge(be[i][j] + X, be[i + ][j + ], , );
}
}
for(int i = ; i <= M; i++) AddEdge(S, be[][i], , );
for(int i = ; i <= N + M - ; i++)
AddEdge(be[N][i], be[N][i] + X, a[N][i], ),
AddEdge(be[N][i] + X, T, , );
printf("%d\n", MCMF());
}
void Solve2() {
memset(head, -, sizeof(head)); num = ;
for(int i = ; i < N; i++) {
for(int j = ; j <= M + i - ; j++) {
AddEdge(be[i][j], be[i + ][j + ], a[i][j], );
AddEdge(be[i][j], be[i + ][j], a[i][j], );
}
}
for(int i = ; i <= M; i++) AddEdge(S, be[][i], , );
for(int i = ; i <= N + M - ; i++) AddEdge(be[N][i], T, a[N][i], INF);
printf("%d\n", MCMF());
}
void Solve3() {
memset(head, -, sizeof(head)); num = ;
for(int i = ; i < N; i++)
for(int j = ; j <= M + i - ; j++) {
AddEdge(be[i][j], be[i + ][j + ], a[i][j], INF);
AddEdge(be[i][j], be[i + ][j], a[i][j], INF);
}
for(int i = ; i <= M; i++) AddEdge(S, be[][i], , );
for(int i = ; i <= N + M - ; i++) AddEdge(be[N][i], T, a[N][i], INF);
printf("%d\n", MCMF());
}
int main() {
memset(head, -, sizeof(head));
M = read(); N = read(); X = (N + M - ) * N;
for(int i = ; i <= N; i++)
for(int j = ; j <= M + i - ; j++)
a[i][j] = read(), be[i][j] = ++tot;
Solve1();
Solve2();
Solve3();
return ;
}
/* */
洛谷P4013 数字梯形问题(费用流)的更多相关文章
- 洛谷P4013 数字梯形问题(费用流)
传送门 两个感受:码量感人……大佬nb…… 规则一:$m$条路径都不相交,那么每一个点只能经过一次,那么考虑拆点,把每一个点拆成$A_{i,j}$和$B_{i,j}$,然后两点之间连一条容量$1$,费 ...
- 洛谷 P4013 数字梯形问题【最大费用最大流】
第一问:因为每个点只能经过一次,所以拆点限制流量,建(i,i',1,val[i]),然后s向第一行建(s,i,1,0),表示每个点只能出发一次,然后最后一行连向汇点(i',t,1,0),跑最大费用最大 ...
- 洛谷P4013数字梯形问题——网络流24题
题目:https://www.luogu.org/problemnew/show/P4013 最大费用最大流裸题: 注意:在第二种情况中,底层所有点连向汇点的边容量应该为inf,因为可以有多条路径结束 ...
- 洛谷 P4013 数字梯形问题
->题目链接 题解: 网络流. #include<cstdio> #include<iostream> #include<queue> #include< ...
- codevs 1913 数字梯形问题 费用流
题目链接 给你一个数字梯形, 最上面一层m个数字, 然后m+1,......m+n-1个. n是层数. 在每个位置, 可以向左下或右下走.然后让你从最顶端的m个数字开始, 走出m条路径, 使得路过的数 ...
- 洛谷 1004 dp或最大费用流
思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...
- 2018.10.15 loj#6010. 「网络流 24 题」数字梯形(费用流)
传送门 费用流经典题. 按照题目要求建边. 为了方便我将所有格子拆点,三种情况下容量分别为111,infinfinf,infinfinf,费用都为validi,jval_{id_{i,j}}valid ...
- 洛谷P4003 无限之环(费用流)
传送门 神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦 到底是得有怎样的脑回路才能一眼看去就是费用流啊…… 建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图 首先, ...
- 洛谷P4012 深海机器人问题(费用流)
题目描述 深海资源考察探险队的潜艇将到达深海的海底进行科学考察. 潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动. 深海机器人在移动中还必须沿途采集海底生物标本.沿途生 ...
随机推荐
- POJ3252 Round Numbers —— 数位DP
题目链接:http://poj.org/problem?id=3252 Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Su ...
- [Selenium] Selenium WebDriver 的下载和安装
为配合较为广泛使用Java 语言的程序员,仅以WebDriver 的Java语言绑定进行讲解. 步骤1:下载并安装Java开发环境 1)在系统中安装JDK(Java开发工具吧,Java Develop ...
- ASP.NET Core:WebAppCoreRESTful
ylbtech-ASP.NET Core:WebAppCoreRESTFul 1.返回顶部 1. 2. 3. 4. 2. Controllers返回顶部 1.HomeControlle ...
- vue项目中的路径别名
每次写引入组件的路径,如果路径嵌套比较深,那么会比较麻烦,我们可以在webpack.base.conf.js,中设置路径的别名,默认webpack设置src的别名为@ 建议配置src下一级目录的别名, ...
- Mac 下的截图技巧
最近想制作GIF图片,截图后,发现没有截出鼠标小效果,自己就查阅了一下资料,总结了不少的截图技巧,这里写下来,权当笔记,方便今后检索,方便别人共享. 方法一: 下载 QQ,在QQ的皮娜好设置里面设置截 ...
- Android Studio新建类头部注释和添加函数注释模板及快捷键
一,Android Studio新建类头部注释 是不是有时候看到这个很心烦 其实Studio中有设置修改这些注释模板的信息的功能 其实很简单,只需要两步: 1.打开Setting设置面板,找到File ...
- string类的常用的几个小东西find,substr
头文件: #include<iostream> #include<string> 定义: string ss; #include<iostream> #includ ...
- PTA【复数相乘】
队友在比赛时A掉的.吊吊吊!!! 主要考虑这些情况吧||| 案例: /* 3i i -3 i -1-i 1+i i 1 -1-i -1-i */ -3 -3i -2i i 2i #include &l ...
- 用hdparm获取硬盘参数
hdparm是Linux下一款能够获取和设置SATA/IDE设备参数的工具. 1.获取硬盘参数 $ sudo hdparm -i /dev/sda$ sudo hdparam -i /dev/sda ...
- IO流案例:1.复制多级文件夹 2.删除多级文件夹
package copy; /* 需求:复制多级文件夹 复制d:\\itcast(包含文件和子文件夹)到模块目录下 分析: d:\\itcast a.txt b.txt javaweb a.xml b ...