2189. 有源汇上下界最大流(最大流上,下界可行流,模板题)

 活动 - AcWing

给定一个包含 n 个点 m 条边的有向图,每条边都有一个流量下界和流量上界。

给定源点 S 和汇点 T,求源点到汇点的最大流。

输入格式

第一行包含四个整数 n,m,S,T。

接下来 m 行,每行包含四个整数 a,b,c,d 表示点 a 和 b 之间存在一条有向边,该边的流量下界为 c,流量上界为 d。

点编号从 1 到 n。

输出格式

输出一个整数表示最大流。

如果无解,则输出 No Solution

数据范围

1≤n≤202
1≤m≤9999
1≤a,b≤n
0≤c≤d≤105

输入样例:
10 15 9 10
9 1 17 18
9 2 12 13
9 3 11 12
1 5 3 4
1 6 6 7
1 7 7 8
2 5 9 10
2 6 2 3
2 7 0 1
3 5 3 4
3 6 1 2
3 7 6 7
5 10 16 17
6 10 10 11
7 10 14 15
输出样例:
43

解析: 

为什么要建新图?
因为此题有上下界,根据我们上题的经验,需要建虚拟源点(S、T)补流;

但是原图有自带的源汇点(s、t),源汇点不保证流量守恒(其他点都保证),所以需要补一条 t —— s 的满容量边,让原图流量守恒,只有满足 {流量守恒容量上限} 我们才可以这样建图。

还记得上题的结论吗,建出这个新图的意义在于:

在这种状态下建出的新图,可以发现若要新图的流对应原图的可行流,需要保证虚拟源点S的出边都满流;

反过来,只要保证新图的流是满流,我们就可以说这个流是原图的一个可行流。

建了这个新图,在这种满流的状态下我们可以发现一些很特殊的性质:
任意两个新图的满流相减(流量相减),S出、T入 这些边的流量相同会抵消掉,剩下的流量居然是新图中 s —— t 的流量(这里s、t可以换成任意两点,只要不是S、T就行,但我们此题要求的与s、t有关)

我们设新图两个满流为 f1、f2,可以得到公式 |f1−f2|=f(s−>t),移下项,f1=f2+f(s−>t);

一开始说过新图的流对应原图可行流,所以 f1 是原图的一个可行流;

若要 f1 最大,因为 f2 固定了(满流),所以要尽可能让 f(s−>t) 大

要求 max(fs−t) 就在新图上跑个 dinic(s−t) 即可,不过要注意删掉 t —— s 的边,不然流量一直循环求不出来

最后答案 ans=满流f2+max(fs−t)

参考至: AcWing 2189. 有源汇上下界最大流(简易又不空洞的理解) - AcWing

这里补充一点: 满流f2== f[idx - 1],是因为 f[idx - 1] 是原图对应新图中的一个可行流,原图的可行流等于 f[idx - 1] + 此边的容量下届,又因为此边的容量下届==0,所以原图的可行流等于 f[idx - 1]。

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 2e2 + 10, M = (1e4 + N) * 2, INF = 0x3f3f3f3f;
int n, m, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N],A[N];void add(int a, int b, int c) {e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx++;e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx++;
}bool bfs() {int hh = 0, tt = 0;memset(d, -1, sizeof d);q[0] = S, d[S] = 0, cur[S] = h[S];while (hh <= tt) {int t = q[hh++];for (int i = h[t]; i != -1; i = ne[i]) {int j = e[i];if (d[j] == -1 && f[i]) {d[j] = d[t] + 1;cur[j] = h[j];if (j == T)return 1;q[++tt] = j;}}}return 0;
}int find(int u, int limit) {if (u == T)return limit;int flow=0;for (int i = cur[u]; i != -1 && flow < limit; i = ne[i]) {int j = e[i];cur[u] = i;if (d[j] == d[u] + 1 && f[i]) {int t = find(j, min(f[i], limit - flow));if (!t)d[j] = -1;f[i] -= t, f[i ^ 1] += t, flow += t;}}return flow;
}int dinic() {int ret = 0, flow;while (bfs())while (flow = find(S, INF)) {ret += flow;}return ret;
}int main() {int s, t;cin >> n >> m >> s >> t;S = 0, T = n + 1;memset(h, -1, sizeof h);for (int i = 1, a, b, c, d; i <= m; i++) {scanf("%d%d%d%d", &a, &b, &c, &d);add(a, b, d - c);A[a] -= c, A[b] += c;}int tot = 0;for (int i = 1; i <= n; i++) {if (A[i] > 0)add(S, i, A[i]), tot += A[i];else if (A[i] < 0)add(i, T, -A[i]);}add(t, s, INF);if (dinic() < tot)cout << "No Solution" << endl;else {int ret = f[idx - 1];S = s, T = t;f[idx - 1] = 0, f[idx - 2] = 0;printf("%d\n", ret + dinic());}return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/694430.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单片机03--按键--寄存器版

GPIO端口相关寄存器&#xff08;STM32F40x芯片&#xff09; 目标&#xff1a; 开关KEY1控制开灯。 分析&#xff1a; KEY1---PA0--->输入---->浮空输入/下拉输入 KEY1不导通时&#xff0c;PA0输入为低电平&#xff0c;KEY1导通时&#xff0c;PA0输入为高电平。 实现…

【Unity】双击txt文件以记事本形式(文本文档)打开

在Unity工程任意Editor文件夹下创建C#脚本&#xff1a;CustomAssetHandler using UnityEngine; using UnityEditor; using UnityEditor.Callbacks;public class CustomAssetHandler {[OnOpenAssetAttribute(1)]public static bool step1(int instanceID, int line){string pat…

Vue中 Runtime-Only和Runtime + Compiler的区别

在 Vue 项目中&#xff0c;Runtime-Only 和 Runtime Compiler 是两种不同的构建方式。 Runtime-Only&#xff08;仅运行时&#xff09;&#xff1a;在 Runtime-Only 构建中&#xff0c;Vue 库只包含运行时的代码&#xff0c;不包含模板编译器。。Runtime Compiler&#xff08…

SpringBoot异步任务获取HttpServletRequest

前言 在使用框架日常开发中需要在controller中进行一些异步操作减少请求时间&#xff0c;但是发现在使用Anysc注解后会出现Request对象无法获取的情况&#xff0c;本文就此情况给出完整的解决方案 原因分析 Anysc注解会开启一个新的线程&#xff0c;主线程的Request和子线程…

SpringBoot的约定优于配置,你的理解是什么?

我从4个点方面来回答。 首先&#xff0c;约定优于配置是一种软件设计的范式&#xff0c;它的核心思想是减少软件开发人员对于配置项的维护&#xff0c;从而让开发人员更加聚焦在业务逻辑上。 SpringBoot就是约定优于配置这一理念下的产物&#xff0c;它类似于Spring框架下的一…

Vue3-组合式Api(重点)

阅读文章你可以收获的知识 1.知道setup语法糖的使用和如何实现的 2.知道在vue3中如何定义响应式数据 3.知道在vue3中如何定义一个计算属性&#xff08;computed&#xff09; 4.知道如何在vue3中使用watch来监听数据 5.知道在vue3如何实现父子通信 6.知道vue3如何使用ref函…

BIM工程师认证相关信息

目录 背景 一、中国图学学会颁发的全国BIM技能等级考试证书 二、中国建设教育协会颁发的BIM证书 背景 BIM工程师证书是建筑信息模型证书&#xff0c;英文全称是Building Information Modeling。对于建筑工程从业人员来说&#xff0c;BIM证书可以证明个人的工作能力&#xf…

软件测试工程师linux学习之系统层面相关命令总结

1 linux系统重启和关机的命令 重启命令&#xff1a;reboot 关机命令&#xff1a;shutdown 这两个命令一般很少用到&#xff0c;我们了解即可。 2 查看日志信息命令 什么是日志&#xff0c;日志就是一个一个普通的文本文件&#xff0c;文件里面记录的是软件运行过程中的信息…

一、初始 Vue

1、Vue 1.1 Vue简介 1.1.1 Vue.js 是什么 Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第…

Stable Diffusion 绘画入门教程(webui)-ControlNet

ControlNet可以说在SD里有着举足轻重的地位&#xff0c;如果没有ControlNet&#xff0c;sd的可玩性和实用性将大大降低。 前面几篇文章介绍了 提示词 和 lora&#xff0c;本篇文章介绍sd里最关键的第三个要素–ControlNet 文章目录 一、它具体能干啥1、艺术字2、改变姿态3、其…

Spring解决循环依赖

目录 什么是spring循环依赖 什么情况下循环依赖可以被处理&#xff1f; spring 如何解决循环依赖 创建A这个Bean的流程 答疑 疑问&#xff1a;在给B注入的时候为什么要注入一个代理对象&#xff1f; 初始化的时候是对A对象本身进行初始化&#xff0c;而容器中以及注入到B…

AI新工具(20240221) OOTDiffusion-虚拟试穿技术的实现;Groq-世界上最快的大模型,每秒可以输出近500个token

OOTDiffusion - 虚拟试穿技术的实现 OOTDiffusion是一种基于潜在扩散的虚拟试穿技术&#xff0c;其主要目的是通过实现控制性的换装融合&#xff0c;让用户能够在虚拟环境中试穿不同的服装。该技术通过融合最新的机器学习算法与图像处理技术&#xff0c;为用户提供了一种新颖的…

vue小记——this(1)

原生和Vue中使用this的这几个坑你都知道吗&#xff1f; - 掘金 (juejin.cn) 在JavaScript中&#xff0c;this是一个特殊的关键字&#xff0c;它在函数被调用时自动定义。this的值在函数被调用时决定&#xff0c;取决于调用的上下文&#xff08;context&#xff09;&#xff0c…

盘点 Udemy 上最受欢迎的免费编程课程

之前给大家推荐过一些油管上的免费学习资源&#xff0c;如果您还没有看过的话可以点击这里前往。 今天再给大家推荐一批Udemy上超高质量并且免费的编程课程&#xff0c;有需要的小伙伴可以学起来了。 1. JavaScript Essentials 第一门免费课程是&#xff1a;JavaScript Essen…

h5网页和 Android APP联调,webview嵌入网页,网页中window.open打开新页面,网页只在webview中打开,没有重开一个app窗口

我是h5网页开发&#xff0c;客户app通过webview嵌入我的页面 点击标题window.open跳转到长图页面&#xff0c;客户的需求是在app里新开一个窗口展示长图页面&#xff0c;window.open打开&#xff0c;ios端是符合客户需求的&#xff0c;但是在安卓端他会在当前webview打开 这…

IDEA实现ssh远程连接本地Linux服务器

文章目录 1. 检查Linux SSH服务2. 本地连接测试3. Linux 安装Cpolar4. 创建远程连接公网地址5. 公网远程连接测试6. 固定连接公网地址7. 固定地址连接测试 本文主要介绍如何在IDEA中设置远程连接服务器开发环境&#xff0c;并结合Cpolar内网穿透工具实现无公网远程连接&#xf…

Unity3d Shader篇(七)— 纹理采样

文章目录 前言一、什么是纹理采样&#xff1f;1. 纹理采样的工作原理2. 纹理采样的优缺点优点缺点 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数 三、效果四、总结使用场景 前言 纹理采样是一种常用的图形学技…

打造智能物品租赁平台:Java与SpringBoot的实践

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

力扣:869. 重新排序得到 2 的幂

枚举和回溯 1.先把int值转换成char数组&#xff0c;之后再用回溯来枚举出全部的排列顺序&#xff0c;在回溯排列过程中要防止同一个数据的重新使用&#xff0c;同时要计算排列中的数字总和&#xff0c;在进行判断这个数据是否是2的幂&#xff0c;使用递归的方式进行&#xff0…

SparkSQL学习01

目录 1.SparkSQL特点1.1易整合1.2统一的数据访问1.3兼容Hive1.4标准的数据连接 2 SparkSQL编程模型DataFrameDataSet2.1 SQL2.2 DataFrame是什么2.3 DataSet是什么2.4 RDD&#xff0c;DataSet&#xff0c;DataFrame 3 SparkSQL核心编程3.1 编程入口3.2 SparkSQL基本编程3.2.1编…