题意

$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 数字梯形问题(费用流)的更多相关文章

  1. 洛谷P4013 数字梯形问题(费用流)

    传送门 两个感受:码量感人……大佬nb…… 规则一:$m$条路径都不相交,那么每一个点只能经过一次,那么考虑拆点,把每一个点拆成$A_{i,j}$和$B_{i,j}$,然后两点之间连一条容量$1$,费 ...

  2. 洛谷 P4013 数字梯形问题【最大费用最大流】

    第一问:因为每个点只能经过一次,所以拆点限制流量,建(i,i',1,val[i]),然后s向第一行建(s,i,1,0),表示每个点只能出发一次,然后最后一行连向汇点(i',t,1,0),跑最大费用最大 ...

  3. 洛谷P4013数字梯形问题——网络流24题

    题目:https://www.luogu.org/problemnew/show/P4013 最大费用最大流裸题: 注意:在第二种情况中,底层所有点连向汇点的边容量应该为inf,因为可以有多条路径结束 ...

  4. 洛谷 P4013 数字梯形问题

    ->题目链接 题解: 网络流. #include<cstdio> #include<iostream> #include<queue> #include< ...

  5. codevs 1913 数字梯形问题 费用流

    题目链接 给你一个数字梯形, 最上面一层m个数字, 然后m+1,......m+n-1个. n是层数. 在每个位置, 可以向左下或右下走.然后让你从最顶端的m个数字开始, 走出m条路径, 使得路过的数 ...

  6. 洛谷 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 ...

  7. 2018.10.15 loj#6010. 「网络流 24 题」数字梯形(费用流)

    传送门 费用流经典题. 按照题目要求建边. 为了方便我将所有格子拆点,三种情况下容量分别为111,infinfinf,infinfinf,费用都为validi,jval_{id_{i,j}}valid ...

  8. 洛谷P4003 无限之环(费用流)

    传送门 神仙题啊……不看题解我可能一年都不一定做得出来……FlashHu大佬太强啦 到底是得有怎样的脑回路才能一眼看去就是费用流啊…… 建好图之后套个板子就好了,那么我们着重来讨论一下怎么建图 首先, ...

  9. 洛谷P4012 深海机器人问题(费用流)

    题目描述 深海资源考察探险队的潜艇将到达深海的海底进行科学考察. 潜艇内有多个深海机器人.潜艇到达深海海底后,深海机器人将离开潜艇向预定目标移动. 深海机器人在移动中还必须沿途采集海底生物标本.沿途生 ...

随机推荐

  1. spring cloud 启动报错-must be declared as an @AliasFor [serviceId], not [name].

    项目加入FeignClient后再启动就报错,具体报错信息如下: org.springframework.core.annotation.AnnotationConfigurationExceptio ...

  2. MYSQL初级学习笔记八:MySQL中常用的函数!(视频序号:初级_45-50)

    知识点十:MySQL中的函数(45-50) 数学函数: 名称 描述 CEIL() 进一取整 FLOOR() 舍一取整 MOD 取余数(取摸) POWER() 幂运算 ROUND() 四舍五入 TRUN ...

  3. HDU - 1269 迷宫城堡(有向图的强连通分量)

    d.看一个图是不是强连通图 s.求出强连通分量,看看有没有一个强连通分量包含所有点. c.Tarjan /* Tarjan算法 复杂度O(N+M) */ #include<iostream> ...

  4. uses-permission和permission详解

    1.<uses-permission>: 官方描述: If an application needs access to a feature protected by a permissi ...

  5. 一个小bug,关于fuse_mount_sys

    在mount.c  中的 int fuse_mount_sys 函数中,如果注销掉 fd的open语句,此时fd一般为0. 然后,用普通用户运行ssfs且不加-f参数,一切显示正常 fuse_moun ...

  6. hdu-3592 World Exhibition(差分约束)

    题目链接: World Exhibition Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 32768/32768 K (Java/ ...

  7. codeforces 667C C. Reberland Linguistics(dp)

    题目链接: C. Reberland Linguistics time limit per test 1 second memory limit per test 256 megabytes inpu ...

  8. (二十六)分类信息的curd-分类信息添加

    分类信息添加: 1.应在在左边的dtree上添加连接(展示所有的分类信息) d.add(...,"/store/adminCategory?method=findAll",&quo ...

  9. 折半插入排序 之通俗易懂,图文+代码详解-java编程

    转自http://blog.csdn.net/nzfxx/article/details/51615439 1.特点及概念介绍 下面给大家讲解一下"二分法查找"这个java基础查找 ...

  10. NYOJ1——A+B Problem NYOJ2——括号配对问题

    A+B Problem 时间限制:3000 ms  |  内存限制:65535 KB 难度:0   描述:此题为练手用题,请大家计算一下a+b的值  输入:输入两个数,a,b 输出:输出a+b的值 样 ...