【最小费用最大流】JZOJ_4802 探险计划

2024-01-30 04:18

本文主要是介绍【最小费用最大流】JZOJ_4802 探险计划,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意

给出一个梯形,每个点上有一个危险值,从底部出发,每次能走到左上或者右上的点。

任务一:找出 m m m条完全不相交的至底至顶的路径
任务二:找出 m m m条仅在数字处相交的路径(可以重复经过点)

对于两个任务,求出最小的危险值总和。

思路

最小费用最大流。

将每个点拆点,对于任务一,给一个限制,任务二则无限制。

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>int n, m, tot, S, E, SS, sum, ans;
int a[81][161], ver[58001], next[58001], head[20004], flow[58001], cost[58001], d[20004], v[20004], pre[20004], p[81][161];inline void add(int u, int v, int f, int c) {ver[++tot] = v;next[tot] = head[u];flow[tot] = f;cost[tot] = c;head[u] = tot;ver[++tot] = u;next[tot] = head[v];flow[tot] = 0;cost[tot] = -c;head[v] = tot;
}inline int spfa() {std::queue<int> q;memset(d, 127 / 3, sizeof(d));memset(v, 0, sizeof(v));memset(pre, 0, sizeof(pre));d[SS] = 0;v[SS] = 1;q.push(SS);while (q.size()) {int u = q.front();q.pop();v[u] = 0;for (register int i = head[u]; i; i = next[i]) {if (!flow[i]) continue;if (d[ver[i]] > d[u] + cost[i]) {d[ver[i]] = d[u] + cost[i];pre[ver[i]] = i;if (!v[ver[i]]) {q.push(ver[i]);v[ver[i]] = 1;}}}}return d[E] < 707406378;
}inline void addflow() {int i = E, mn = 2147483647;while (pre[i]) {mn = std::min(mn, flow[pre[i]]);i = ver[pre[i] ^ 1];}ans += mn * d[E];i = E;while (pre[i]) {flow[pre[i]] -= mn;flow[pre[i] ^ 1] += mn;i = ver[pre[i] ^ 1];}
}int main() {scanf("%d %d", &n, &m);int tj = 0, sum = (m + m + n - 1) * n / 2;tot = 1;for (register int i = 1; i <= n; i++)for (register int j = 1; j < m + i; j++) {scanf("%d", &a[i][j]);p[i][j] = ++tj;add(p[i][j], p[i][j] + sum, 1, 0);}S = 0;E = 2 * sum + 1;SS = 2 * sum + 2;add(SS, S, m, 0);for (register int i = 1; i < m + n; i++)add(S, p[n][i], m, a[n][i]);for (register int i = 1; i <= m; i++)add(p[1][i] + sum, E, m, 0);for (register int i = 2; i <= n; i++) {for (register int j = 1; j < m + i; j++) {if (j < m + i - 1) add(p[i][j] + sum, p[i - 1][j], 1, a[i - 1][j]);if (j > 1) add(p[i][j] + sum, p[i - 1][j - 1], 1, a[i - 1][j - 1]);}}while (spfa())addflow();printf("%d\n", ans);tot = 1;ans = 0;memset(head, 0, sizeof(head));add(SS, S, m, 0);for (register int i = 1; i < m + n; i++)add(S, p[n][i], m, a[n][i]);for (register int i = 1; i <= m; i++)add(p[1][i] + sum, E, m, 0);for (register int i = 1; i <= n; i++) {for (register int j = 1; j < m + i; j++) {add(p[i][j], p[i][j] + sum, m, 0);if (i > 1 && j < m + i - 1) add(p[i][j] + sum, p[i - 1][j], 1, a[i - 1][j]);if (i > 1 && j > 1) add(p[i][j] + sum, p[i - 1][j - 1], 1, a[i - 1][j - 1]);}}while (spfa())addflow();printf("%d", ans);	
}

这篇关于【最小费用最大流】JZOJ_4802 探险计划的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/659075

相关文章

LeetCode--155 最小栈

题目 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。push(x) -- 将元素 x 推入栈中。pop() -- 删除栈顶的元素。top() -- 获取栈顶元素。getMin() -- 检索栈中的最小元素。 示例 MinStack minStack = new MinStack();minStack.push(-2);minStack.push

如何设置windows计划任务

如何设置windows计划任务 前言:在工作过程中写了一个python脚本,用于调用jira接口查询bug单数量,想要在本地定时任务执行,每天发送到钉钉群提醒,写下操作步骤用于记录。 1. 准备 Python 脚本 确保你的 Python 脚本已经保存到一个文件,比如 jira_reminder.py。 2. 创建批处理文件 为了方便任务计划程序运行 Python 脚本,创建一个批处理文

Python临时计划

时间:6月——9月        入门

关于修改计算机的处理器数和最大内存数的问题

问题描述: 刚开始本来是想让计算机的运行速度运行的快点,于是在网上搜索如何让计算机的运行速度更快,找到了一种关于修改计算机内存数和计算机的处理核数可以让计算机运行的更快。 遇到问题: 当我通过命令msconfig →引导→高级选项→勾选了处理器数和最大内存数,然后重启,结构整个计算机都卡的要死,于是记录下来。网上的答案有时候真的是很不负责任,也有可能是自己技术不到位。 结果:取消处理器和内

Ural 1277 cops ans thieves (最小割模型)

题目地址 :http://acm.timus.ru/problem.aspx?space=1&num=1277 这里我们要拆点。把一个点拆成i,i' 。如何 i,j有边 ,在建边(i,j',inf),(j,i',inf)。 然后每个点点边(i',i,R[i])。这样建边以后,若要阻止 s到f的路径,那么必须破败一些边,那么我们为了是的边权最小,必须破坏边权小于inf的边,对应的就是图中拆

动态规划DP--斐波那契数、爬楼梯、使用最小花费爬楼梯等示例代码

动态规划DP 文章目录 动态规划DP509. 斐波那契数70. 爬楼梯746. 使用最小花费爬楼梯62. 不同路径63. 不同路径II343.整数拆分 509. 斐波那契数 509. 斐波那契数 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0,F(1) =

【数学】100332. 包含所有 1 的最小矩形面积 II

本文涉及知识点 数学 LeetCode100332. 包含所有 1 的最小矩形面积 II 给你一个二维 二进制 数组 grid。你需要找到 3 个 不重叠、面积 非零 、边在水平方向和竖直方向上的矩形,并且满足 grid 中所有的 1 都在这些矩形的内部。 返回这些矩形面积之和的 最小 可能值。 注意,这些矩形可以相接。 示例 1: 输入: grid = [[1,0,1],[1,1,1]]

Day 31:100334. 包含所有1的最小矩形面积Ⅰ

Leetcode 100334. 包含所有1的最小矩形面积Ⅰ 给你一个二维 **二进制 **数组 grid。请你找出一个边在水平方向和竖直方向上、面积 最小 的矩形,并且满足 grid 中所有的 1 都在矩形的内部。 返回这个矩形可能的 **最小 **面积。 确定首次出现 1 的第一行 top,最后一次出现 1 的最后一列 r,最后一次出现 1 的最后一行 bottom,首次出现的第

LeetCode 算法:二叉树的最大深度 c++

原题链接🔗:二叉树的最大深度 难度:简单⭐️ 题目 给定一个二叉树 root ,返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1: 输入:root = [3,9,20,null,null,15,7] 输出:3 示例 2: 输入:root = [1,null,2] 输出:2 提示: 树中节点的数量在 [0, 104] 区间内。-1