技术标签: 网络流
Step1 Problem:
给你 n 个点,m 条流量下界是 low ,上界是 up 的单向边。问你能否满足每时每刻每条边的流量都在 [low, up] 范围内,如果不满足输出 NO, 满足输出 YES 同时输出每条边的流量。
Step2 Ideas:
上下界网络流和平常的网络流不同在于多出了两个点:超级源点 S, 超级汇点 T.
超级源点 S:每条边下界流量都由 S 流出,这样原图就可以变成没有下界的容量为 up-low 的图了。
超级汇点 T:T 是用来判断 流入每个点的流量 是否够 它流出的下界。
知道 S, T 的作用后:
例如:一条边 u -> v,下界 low, 上界 up.
那么 S -> v 流入 low,u -> T 流入 low,u-> v 流入 up-low. (这样就没有下界了)
S -> v 流入 low:S 充当了 u 流向 v 的下界
u -> T 流入 low:如果 u 有流量 low 流入 T,代表有流量 low 可以到达 u,那么 u->v 的下界流量肯定能满足
u-> v 流入 up-low:S 充当了 u 流向 v 的下界,所以我的上下界都得减少 low.
对于新图跑 S 到 T 的最大流,如果 T 收到流量是满流的 或者 S 发出去的流量是满流的,就代表所有下界流量都能满足。
Step3 Code:
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int M = 50000;
const int N = 500;
struct node
{
int to, cap, next;
}Map[M];
int head[N], cnt;
int lsum[N], bl[N*N];
int vis[N], cur[N];
int ans[N*N];
bool bfs(int s, int e)
{
memset(vis, -1, sizeof(vis));
queue<int> q;
q.push(s);
vis[s] = 0;
while(!q.empty())
{
s = q.front(), q.pop();
for(int i = head[s]; ~i; i = Map[i].next)
{
int to = Map[i].to, cap = Map[i].cap;
if(cap && vis[to] == -1)
{
vis[to] = vis[s] + 1;
q.push(to);
}
}
}
if(vis[e] == -1) return 0;
else return 1;
}
int dfs(int s, int e, int f)
{
if(s == e) return f;
int ans = 0;
for(int &i = cur[s]; ~i; i = Map[i].next)
{
int to = Map[i].to, &cap = Map[i].cap;
if(vis[to] > vis[s] && cap)
{
int d = dfs(to, e, min(f, cap));
if(d)
{
cap -= d;
Map[i^1].cap += d;
f -= d;
ans += d;
if(!f) break;
}
}
}
if(ans) return ans;
vis[s] = -1;
return 0;
}
int dinic(int s, int e)
{
int ans = 0;
while(bfs(s, e))
{
memcpy(cur, head, sizeof(head));
ans += dfs(s, e, inf);
}
return ans;
}
void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
memset(lsum, 0, sizeof(lsum));
memset(bl, 0, sizeof(bl));
}
void add(int u, int v, int cap)
{
Map[cnt] = (node){v, cap, head[u]};
head[u] = cnt++;
Map[cnt] = (node){u, 0, head[v]};
head[v] = cnt++;
}
int main()
{
int T, n, m, u, v, low, up;
scanf("%d", &T);
while(T--)
{
init();
scanf("%d %d", &n, &m);
int S = 0, T = n+1;
for(int i = 1; i <= m; i++)
{
scanf("%d %d %d %d", &u, &v, &low, &up);
add(u, v, up-low);
lsum[v] += low; //流入 v 的下界和
lsum[u] -= low; //流出 u 的下界和
bl[i] = low;
}
int sum = 0;// S 发出去的流量
for(int i = 1; i <= n; i++)
{
if(lsum[i] > 0) {
sum += lsum[i];
add(S, i, lsum[i]);//流入比流出多
}
if(lsum[i] < 0) add(i, T, -lsum[i]);//流出比流入多
}
if(sum != dinic(S, T)) {
//如果最大流不等于发出去的流量,则不满足
printf("NO\n");
}
else {
printf("YES\n");
for(int i = 1; i <= m; i++) {
//每条边在下界的基础上多流了多少流量
int id = (i-1)*2;
ans[i] = Map[id^1].cap;
}
for(int i = 1; i <= m; i++)
{
printf("%d\n", ans[i]+bl[i]);
}
}
printf("\n");
}
return 0;
}
前言在日常的Java编程中,会遇到需要将int类型转换成String类型的情况,这时候可以使用Integer类进行操作。在转换的时候,需要注意对象是否为null一、integer转String类型存在三种方法,核心都是静态方法toString()//方法一:Integer类的静态方法toString()Integer a = 3;String str = Integer.toString(a) //方法二:Integer类的成员方法toString()Integer a = 3;Stri
1、string 转 number 类型:有两种方法(1)parseInt()、parseFloat() (2)Number()区别:parseInt()、parseFloat() 转换第一个无效字符之前的字符串,例如parseInt(1.2.3)为1,parseFloat(1.2.3)为1.2;Number()如果是不能转换的字符串则输出NaN,例如Number(1.2.3)为Na...
WPF学习之二:XAML学习一、 什么是XAML?什么是XAML呢?XAML是扩展应用程序标记语言(Extensible Application Markup Language),它是微软基于XML开发的一种声明式的用于创建UI的语言。XAML一般都是定义.xaml后缀格式的文件中。二、 XAML中的元素XML中的每个通过尖括号括起来的标记都称之为元素,XAML是基于XML产
【导语】在事业单位考试中,计算机专业知识的复习向来是考生复习备考阶段的一大重点,其中中公事业单位考试网为计算机基础知识的复习为考生提供知识点梳理,帮助考生备考!计算机系统的主要性能指标包括:字长、主频、运算速度、存取周期、存取容量。1.字长字长是指计算机可以直接处理的二进制数据的位数。它直接影响计算机的计算精度、速度和功能,是计算机的一个重要技术指标。字长越长,一个字所能表示的数据精度就越高,数据...
分享几个常用的Xcode插件。第一个, 规范注释生成器VVDocumenter。顾名思义, 它可以很方便的为你自动添加注释使用效果如下:下载链接:https://github.com/onevcat/VVDocumenter-Xcode使用说明:1.前往GitHub下载工程文件:VVDocumenter-Xcode2.用Xcode打开工程,Command + BBuild成功后,可以在~/Libr
一、原因 当使用CSI连接的方式将摄像头模块连接树莓派后,在/dev/中找不到video0,因此使用一些第三方库(如Opencv或RaspberryCam)去调用摄像头时,无法调用成功。二、解决方法 使用root权限打开/etc/modules 然后添加一行:bcm2835-v4l2(注意,这里是4l2不是412),然后重启PI。三、效果 四、Ra...
反射概述:AVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象三种方式Object类的...
本次操作由于这台计算机的限制而被取消.请与您的系统管理员联系运行---gpedit.msc进入gpedit.msc组策略,用户配置管理模板Windows组件Windows资源管理器防止从我的电脑访问驱动器(从上往下数第12行),发现是默认设置(未配置)并没有被修改设置,修改配置为已启用,并选择C盘,确定后再重新进入,将配置改回未配置,C盘恢复正常试下如下操作:运行---gpedit.msc进入gp...
今天看到杨绛的一段话, 深有感触, 分享如下: 有些人之所以不断成长,就绝对是有一种坚持下去的力量。好读书,肯下功夫,不仅读,还做笔记。人要成长,必有原因,背后的努力与积累一定数倍于普通人。所以,关键还在于自己。 对, 关键还在于自己。 以此自勉!
题面Description现在小朋友们最喜欢的”喜羊羊与灰太狼”,话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x
(一)slotslot插槽,是Vue提供的一种HTML模版,由子组件提供的一种暴露给父组件的可以传入自定义内容的出口。slot 有 匿名插槽,具名插槽,作用域插槽 三种。匿名插槽(一个元素里只能有一个匿名插槽)// 子组件<div class="child1"> <!--匿名插槽--> <slot>匿名插槽按钮</slot></div>// 父组件<child1> <div>
系统自带的vim版本太低了,因此利用homebrew快捷下载一个macvim2019.12.28本文介绍下在mac下安装macvim并配置vimplus的流程。首先,安装homebrew,打开终端,复制下面代码回车运行:$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/instal...