P4013 数字梯形问题(拆点+最大费最大流)
时间:2021-04-22
本文章向大家介绍P4013 数字梯形问题(拆点+最大费最大流),主要包括P4013 数字梯形问题(拆点+最大费最大流)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述:
给定一个由 n 行数字组成的数字梯形如下图所示。
梯形的第一行有 m 个数字。从梯形的顶部的 m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。
分别遵守以下规则:
-
从梯形的顶至底的 m 条路径互不相交;
-
从梯形的顶至底的 m条路径仅在数字结点处相交;
3.从梯形的顶至底的 m条路径允许在数字结点相交或边相交。
思路:最大费用最大流,拆点,一个问建一次图,
第一问:要路径不相交,意思就是m条路径的边和节点都不相交,则拆点后两点连容量为1,价值为自身数字num的边,
限制为只选择一次,然后上面点的出点和下边两个点的入点连边,容量也设置为1.边没有价值,设为0,然后s对m个起点
连容量为1,价值为0的边,表示选取m条路径,再把最下层的所有点的出点与汇点连边,容量为1,费用为0;
第二问:数字可以重复选择,路径还是不能重复,那么就把拆点后的两点容量设置为inf,表示可以无线选取,边的容量不变,与汇点
连边容量也设置为inf,因为从一个点流出的流量可能比1大(最后一个点是多条路径的终点)
第三问:边和路径都可以重复选择,就在上题基础上把边的容量也设置为inf就好了,总之源点与m个起始点的容量为1的边不变就行.
第三问也可以用dp做,时间复杂度O(n*m)速度更快
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 600005; const int inf = 0x3f3f3f3f; struct edge { int f, t, nxt; ll flow, w; }e[maxn * 2]; int hd[maxn], tot = 1; void add(int f, int t, ll flow, ll w) { e[++tot] = { f,t,hd[f],flow ,w }; hd[f] = tot; e[++tot] = { t,f,hd[t],0,-w }; hd[t] = tot; } int s, t; int dis[maxn], pre[maxn]; ll maxflow, mincost; ll cyf[maxn]; bool inque[maxn]; int m, n, total; bool spfa() { for (int i = 1; i <=total*2+3; i++) { dis[i] = -inf; inque[i] = 0; } dis[s] = 0, inque[s] = 1, cyf[s] = inf; queue<int>q; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); inque[u] = 0; for (int i = hd[u]; i; i = e[i].nxt) { int v = e[i].t; if (e[i].flow > 0 && dis[u] + e[i].w > dis[v]) { pre[v] = i; cyf[v] = min(cyf[u], e[i].flow); dis[v] = dis[u] + e[i].w; if (!inque[v]) { inque[v] = 1; q.push(v); } } } } return dis[t] != -inf; } void mcmf() { maxflow = mincost = 0; while (spfa()) { int x = t; maxflow += cyf[t]; mincost += dis[t] * cyf[t]; while (x != s) { int i = pre[x]; e[i].flow -= cyf[t]; e[i ^ 1].flow += cyf[t]; x = e[i].f; } } } int num[25][3000]; int res[25][3000]; int main() { //freopen("test.txt", "r", stdin); scanf("%d%d", &m, &n); total = (2 * m + n - 1) * n / 2; s = total*2 + 1, t = s + 1; int nxt , pre; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m + i - 1; j++) { scanf("%d", &num[i][j]); } } nxt = 0, pre = 0; for (int i = 1; i <= n; i++) { nxt += i + m - 1; for (int j = 1; j <= m + i-1; j++) { add(pre + j, pre + j + total, 1, num[i][j]); if (i == n)continue; add(pre + j+total, nxt + j, 1, 0); add(pre + j+total, nxt + j + 1, 1, 0); } pre = nxt; } for (int i = 1; i <= m; i++) { add(s, i, 1, 0); } for (int i = total - (m + n - 1) + 1; i <= total; i++) { add(i + total, t, 1, 0); } mcmf(); printf("%lld\n", mincost); memset(hd, 0, sizeof(hd)); tot = 1; nxt = 0, pre = 0; for (int i = 1; i <= n; i++) { nxt += i + m - 1; for (int j = 1; j <= m + i - 1; j++) { add(pre + j, pre + j + total, inf, num[i][j]); if (i == n)continue; add(pre + j + total, nxt + j, 1, 0); add(pre + j + total, nxt + j + 1, 1, 0); } pre = nxt; } for (int i = 1; i <= m; i++) { add(s, i,1, 0); } for (int i = total - (m + n - 1) + 1; i <= total; i++) { add(i + total, t, inf, 0); } mcmf(); printf("%lld\n", mincost); //dp /*for (int i = n; i>=1 ; i--) { for (int j = 1; j <= m + i - 1; j++) { res[i][j] = max(res[i + 1][j], res[i + 1][j + 1]) + num[i][j]; } } ll ans = 0; for (int i = 1; i <= m; i ++) { ans += res[1][i]; } printf("%lld\n", ans);*/ memset(hd, 0, sizeof(hd)); tot = 1; nxt = 0, pre = 0; for (int i = 1; i <= n; i++) { nxt += i + m - 1; for (int j = 1; j <= m + i - 1; j++) { add(pre + j, pre + j + total, inf, num[i][j]); if (i == n)continue; add(pre + j + total, nxt + j, inf, 0); add(pre + j + total, nxt + j + 1, inf, 0); } pre = nxt; } for (int i = 1; i <= m; i++) { add(s, i, 1, 0); } for (int i = total - (m + n - 1) + 1; i <= total; i++) { add(i + total, t, inf, 0); } mcmf(); printf("%lld\n", mincost); return 0; }
原文地址:https://www.cnblogs.com/MYMYACMer/p/14691442.html
- 用户登录安全框架shiro—用户的认证和授权(一)
- 第一道防线__SpringMVC配置拦截器
- Web层框架对网站中所有异常的统一处理
- Spring MVC__自定义日期类型转换器
- 解决在控制层springmvc框架发出的400状态的错误
- 解决springmvc在单纯返回一个字符串对象时所出现的乱码情况(极速版)
- MySQL日志文件之错误日志和慢查询日志详解
- 采用HTML5之"data-"机制自由提供数据
- Spring和SpringMVC父子的容器之道---[上篇]
- 快速完成(图片旋转,查看原图)
- Jsp中格式化时间戳的常用标签
- 反射+自定义注解---实现Excel数据列属性和JavaBean属性的自动映射
- 后台模板管理系统___左侧菜单数据的异步加载
- Shiro眼皮下玩ajax,玩出302 Found
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- R语言有极值(EVT)依赖结构的马尔可夫链(MC)对洪水极值分析
- RxSwift 封装 CoreBluetooth(一) 配置
- Golang 操作Excel文件
- 腾讯云TKE-搭建prometheus监控(一)
- Android开发中ProgressDialog简单用法示例
- Android实现拍照及图片裁剪(6.0以上权限处理及7.0以上文件管理)
- Android仿微信调用第三方地图应用导航(高德、百度、腾讯)
- Android数据共享 sharedPreferences 的使用方法
- Android NavigationBar问题处理的方法
- mac系统下载、安装、使用Java8教程
- React Native学习之Android的返回键BackAndroid详解
- Android动态添加view的方法示例
- Android开发之瀑布流控件的实现与使用方法示例
- Android自定义View绘制四位数随机码
- Anroid四大组件service之本地服务的示例代码