最小费用最大流(洛谷-P3381)

2024-06-17 19:48

本文主要是介绍最小费用最大流(洛谷-P3381),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目描述

如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

输入输出格式

输入格式:

第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。

输出格式:

一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。

输入输出样例

输入样例#1:

4 5 4 3
4 2 30 2
4 3 20 3
2 3 20 1
2 1 30 9
1 3 40 5

输出样例#1:

50 280

思路:最小费用最大流模版题,利用 zkw 费用流解决

源代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<LL,LL>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL res=0; while(b){if(b&1)res=(res+a)%mod; a=(a<<=1)%mod; b>>=1; } return res%mod;}
LL quickPowMod(LL a, LL b,LL mod){ LL res=1,k=a; while(b){if((b&1))res=multMod(res,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return res%mod;}
LL getInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-10;
const int MOD = 998244353;
const int N = 500000+5;
const int dx[] = {-1,1,0,0,1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;struct Edge {int to;int next;int cap, cost;
} edge[N];
int head[N], tot;
bool vis[N];
int dis[N], level[N];void addEdge(int x, int y, int cap, int cost) {edge[++tot].to = y;edge[tot].next = head[x];edge[tot].cap = cap;edge[tot].cost = cost;head[x] = tot;edge[++tot].to = x;edge[tot].next = head[y];edge[tot].cap = 0;edge[tot].cost = -cost;head[y] = tot;
}bool SPFA(int S, int T, int n) {memset(dis, INF, sizeof(dis));memset(vis, false, sizeof(vis));memset(level, 0, sizeof(level));dis[S] = 0;level[S] = 1;vis[S] = true;deque<int> Q;Q.push_back(S);while (!Q.empty()) {int x = Q.front();Q.pop_front();vis[x] = false;for (int i = head[x]; i != -1; i = edge[i].next) {int to = edge[i].to;if (dis[to] > dis[x] + edge[i].cost && edge[i].cap > 0) {dis[to] = dis[x] + edge[i].cost;level[to] = level[x] + 1;if (!vis[to]) {vis[to] = true;if (!Q.empty() && dis[to] < dis[Q.front()])Q.push_front(to);elseQ.push_back(to);}}}}return dis[T] != dis[n + 1];
}bool flag = false;
int dfs(int x, int T, int t, int &flow, int &cost) {if (x == T) {flow += t;flag = true;return t;}int num = 0, newFlow = 0;for (int i = head[x]; i != -1; i = edge[i].next) {int to = edge[i].to;if (t == num)break;if (dis[x] + edge[i].cost == dis[to] && level[x] + 1 == level[to] && edge[i].cap > 0) {newFlow = dfs(to, T, min(t - num, edge[i].cap), flow, cost);num += newFlow;cost += newFlow * edge[i].cost;edge[i].cap -= newFlow;edge[i ^ 1].cap += newFlow;}}return num;
}
void zkw(int S, int T, int n) {int flow = 0, cost = 0;while (SPFA(S, T, n)) {flag = true;while (flag) {flag = false;dfs(S, T, INF, flow, cost);}}printf("%d %d\n", flow, cost);
}int main() {int n, m;while (scanf("%d%d", &n, &m) != EOF) {memset(head, -1, sizeof(head));tot = 1;int S, T;scanf("%d%d", &S, &T);for (int i = 1; i <= m; i++) {int x, y, cap, cost;scanf("%d%d%d%d", &x, &y, &cap, &cost);addEdge(x, y, cap, cost);}zkw(S, T, n);}return 0;
}

 

这篇关于最小费用最大流(洛谷-P3381)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

LeetCode--155 最小栈

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

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

问题描述: 刚开始本来是想让计算机的运行速度运行的快点,于是在网上搜索如何让计算机的运行速度更快,找到了一种关于修改计算机内存数和计算机的处理核数可以让计算机运行的更快。 遇到问题: 当我通过命令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

「LeetCode 084」最大面积

题目地址: https://leetcode-cn.com/problems/largest-rectangle-in-histogram/ 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。 example 第一种方法,我们先确定左右两个边界,然后找边界中的最小值。比方说,我们左边界确定

最大子数组问题(第4章:分治策略)

求子数组的最大和 题目描述: 输入一个整形数组,数组里有正数也有负数。 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。 求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此输出为该子数组的和18。   思路 1 当我们加上一个正数时,和会

洛谷 P10584 [蓝桥杯 2024 国 A] 数学题(整除分块+杜教筛)

题目 思路来源 登录 - Luogu Spilopelia 题解 参考了两篇洛谷题解,第一篇能得出这个式子,第二篇有比较严格的复杂度分析 结合去年蓝桥杯洛谷P9238,基本就能得出这题的正确做法 代码 #include<bits/stdc++.h>#include<iostream>#include<cstdio>#include<map>#include<uno