@description@

给定一个有源点与汇点的图 G,并对于每一条边 (u, v) 给定 f(u, v) 与 c(u, v)。f 表示流量,c 表示容量。G 不一定是合法的网络流。

求一个新图 G',使得 G' 是一个合法网络流(流量守恒与容量限制) ,且 ∑(|f'(u, v) - f(u, v)| + |c'(u, v) - c(u, v)|) 最小。

输出这个最小值。

input

第一行两个整数 n 和 m (2 ≤ n ≤ 100, 0 ≤ m ≤ 100),表示点数与边数。

接下来 m 行每行 4 个整数 ui, vi, ci, fi (1 ≤ ui, vi ≤ n, ui ≠ vi, 0 ≤ ci, fi ≤ 1 000 000) ,表示图 G 中有一条 (ui, vi) 且容量为 ci,流量为 fi 的图。

保证 1 为源点而 n 为汇点。输入无自环,但可能有重边。

output

输出一个整数,表示最小值。

sample input1

2 1

1 2 2 1

sample output1

0

note

注意不一定是最大流,比如上面的样例。

sample input2

4 2

2 3 1 1

3 2 1 1

sample output2

0

note

可能会有独立于源点和汇点的流存在。

@solution@

新的容量 c'(u, v) = max(c(u, v), f'(u, v))。

贪心一下就可以得到这个结果。

因此,我们分类讨论:

(1)c(u, v) >= f(u, v)。

当我们将 f(u, v) - 1,则费用 + 1。

因为一条边流量减少等于其反向边流量增加,我们连 (v, u),容量为 f(u, v),费用为 1。

当我们将 f(u, v) + 1,如果新的流量不超过 c(u, v),则费用 + 1;否则,费用 + 2。

因为新的流量越大单位费用不会减少,所以我们连两类边:一是 (u, v),容量为 c(u, v) - f(u, v),费用为 1;二是 (u, v),容量为 inf,费用为 2。

每次沿最短路增广,所以必然先走一类边再走二类边。

(2)c(u, v) < f(u, v)

与上面不同的是,这个时候必然会产生费用 f(u, v) - c(u, v)。我们可以先把这部分费用算入答案。

当 f(u, v) + 1,费用 + 2。连 (u, v),容量为 inf,费用为 2。

当 f(u, v) - 1,如果新的流量 >= c(u, v),则不会产生费用:因为这部分费用在一开始就被算入了答案;否则费用 + 1。

因此,我们依然是连两类边:一是 (v, u),容量为 f(u, v) - c(u, v),费用为 0;二是 (v, u),容量为 c(u, v),费用为 1。

为了使流量守恒,我们统计一个点的进入的流量与出去的流量之差。

如果进入的流量 > 出去的流量,则多出来的流向一个超级汇点流去,即建边 (i, tt),容量为差值,费用为 0。

如果进入的流量 < 出去的流量,则差的流由一个超级源点流过来,即建边 (ss, i),容量为差值,费用为 0。

原图中源点 s 和汇点 t 不一定满足流量守恒怎么办?连边 (t, s),容量为 inf,费用为 0。

这样子,ss 向 tt 跑最小费用最大流即可。

@accepted code@

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXV = 400 + 5;
const int MAXE = 20000 + 5;
const int INF = int(1E9);
struct FlowGraph{
struct edge{
int to, flow, cap, dis;
edge *nxt, *rev;
}edges[MAXE], *adj[MAXV], *cur[MAXV], *ecnt;
int s, t, cost, dist[MAXV];
void init() {
ecnt = &edges[0];
for(int i=0;i<MAXV;i++) adj[i] = NULL;
}
void addedge(int u, int v, int c, int w) {
edge *p = (++ecnt), *q = (++ecnt);
p->to = v, p->flow = 0, p->cap = c, p->dis = w;
p->nxt = adj[u], adj[u] = p;
q->to = u, q->flow = 0, q->cap = 0, q->dis = -w;
q->nxt = adj[v], adj[v] = q;
p->rev = q, q->rev = p;
}
bool inque[MAXV];
bool relabel() {
queue<int>que;
for(int i=0;i<MAXV;i++) dist[i] = INF, cur[i] = adj[i];
que.push(s); dist[s] = 0, inque[s] = true;
while( !que.empty() ) {
int f = que.front(); que.pop(); inque[f] = false;
for(edge *p=adj[f];p;p=p->nxt) {
if( p->cap > p->flow && dist[f] + p->dis < dist[p->to] ) {
dist[p->to] = dist[f] + p->dis;
if( !inque[p->to] ) {
que.push(p->to);
inque[p->to] = true;
}
}
}
}
return !(dist[t] == INF);
}
bool vis[MAXV];
int aug(int x, int tot) {
if( x == t ) {
cost += tot*dist[x];
return tot;
}
int sum = 0; vis[x] = true;
for(edge *&p=cur[x];p;p=p->nxt) {
if( p->cap > p->flow && !vis[p->to] && dist[p->to] == dist[x] + p->dis ) {
int del = aug(p->to, min(tot-sum, p->cap-p->flow));
p->flow += del, p->rev->flow -= del, sum += del;
if( sum == tot ) break;
}
}
vis[x] = false;
return sum;
}
int min_cost_max_flow(int _s, int _t) {
s = _s, t = _t; int flow = 0; cost = 0;
while( relabel() )
flow += aug(s, INF);
return flow;
}
}G;
int deg[MAXV];
int main() {
G.init(); int n, m;
scanf("%d%d", &n, &m);
int s = 1, t = n, ss = 0, tt = n + 1, ans = 0;
for(int i=1;i<=m;i++) {
int u, v, c, f; scanf("%d%d%d%d", &u, &v, &c, &f);
if( c < f ) {
G.addedge(v, u, c, 1);
G.addedge(u, v, f - c, 0);
G.addedge(u, v, INF, 2);
ans += f - c;
deg[u] += c, deg[v] -= c;
}
else {
G.addedge(v, u, f, 1);
G.addedge(u, v, c - f, 1);
G.addedge(u, v, INF, 2);
deg[u] += f, deg[v] -= f;
}
}
for(int i=1;i<=n;i++) {
if( deg[i] < 0 ) G.addedge(ss, i, -deg[i], 0);
if( deg[i] > 0 ) G.addedge(i, tt, deg[i], 0);
}
G.addedge(t, s, INF, 0);
G.min_cost_max_flow(ss, tt);
printf("%d\n", ans + G.cost);
}

@details@

除此之外,还有另一种建模方法:

考虑一个零流的图,它本身会产生一定的费用。

我们给某一条边的流量增加,费用可能会减少(更接近原图 G 中的流量),不变或者是增加。

我们建一个图,使得这个图可以满足让流量增加过后费用的变化规律。然后在这个图上找一个最小费用循环流。

@codeforces - 708D@ Incorrect Flow的更多相关文章

  1. CF708D Incorrect Flow

    CF708D Incorrect Flow 有源汇上下界最小费用可行流.(= =) 对每条给定的边连边: 首先\(f_i\)是给定的,所以要有一条这个边而且要流满,先\(a_i-b_i\)连一条上下界 ...

  2. 【CF708D】Incorrect Flow 最小费用可行流

    [CF708D]Incorrect Flow 题意:给你一个点数为n,边数为m的流网络,每条边有一个容量c和流量f,这个网络可能是不合法的.你可以花费1的代价使c或f减少或增加1,可以修改无限次.你不 ...

  3. 题解-CF708D Incorrect Flow

    题面 CF708D Incorrect Flow 给一张网络流图,可能有流量不守恒或者流量超过容量的情况,求最少的将某条边流量或容量 \(\pm 1\) 的操作次数使得网络流图正确. 数据范围:\(1 ...

  4. CodeForces - 269C Flawed Flow

    http://codeforces.com/problemset/problem/269/C 题目大意: 给定一个边没有定向的无法增广的残量网络且1是源点,n是汇点,给定每条边中的流.  让你把所有边 ...

  5. codeforces 269C Flawed Flow(网络流)

    Emuskald considers himself a master of flow algorithms. Now he has completed his most ingenious prog ...

  6. Codeforces 269C Flawed Flow (看题解)

    我好菜啊啊啊.. 循环以下操作 1.从队列中取出一个顶点, 把哪些没有用过的边全部用当前方向. 2.看有没有点的入度和 == 出度和, 如果有将当前的点加入队列. 现在有一个问题就是, 有没有可能队列 ...

  7. Codeforces 270E Flawed Flow 网络流问题

    题意:给出一些边,给出边的容量.让你为所有边确定一个方向使得流量最大. 题目不用求最大流, 而是求每条边的流向,这题是考察网络流的基本规律. 若某图有最大,则有与源点相连的边必然都是流出的,与汇点相连 ...

  8. Codeforces 708D 费用流 (呃我们的考试题)

    NB的题目背景 输入输出一样 考试的时候貌似只有gzz一个人搞出来了 %gzz 思路: 分情况讨论 add(x,y,C,E) C是费用 E是流量 1. f>c add(x,y,2,inf),ad ...

  9. Codeforces 708D 上下界费用流

    给你一个网络流的图 图中可能会有流量不平衡和流量>容量的情况存在 每调整一单位的流量/容量 需要一个单位的花费 问最少需要多少花费使得原图调整为正确(可行)的网络流 设当前边信息为(u,v,f, ...

随机推荐

  1. day37 02-Hibernate二级缓存:二级缓存的散装数据

    一级缓存存放的是对象的地址.把对象的地址缓存下来了.二级缓存里面存放的是对象的散装数据.你再去获取的时候,因为一级缓存的生命周期结束了,它会从二级缓存中获取.从二级缓存中获取,因为它又会得到一个对象. ...

  2. for循环取出每个i的值

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...

  3. UE4物理模块(一)---概述与可视化调试

    UE4.21前的版本采用的是NVIDIA的PhysX做为其默认的物理引擎,用于计算3D世界的碰撞查询与物理模拟.自4.21版本开始改物理调用接口,但这并不是闲来重构代码,果然在2019GDC大会上放出 ...

  4. chrome 浏览器 添加访问助手来访问网上应用商店

    chrome浏览器的强大之处,在于可以chrome浏览器的扩展程序来实现很多功能.然而不能下载扩展程序.可以借助chrome访问助手来实现: 下载chrome访问助手:https://pan.baid ...

  5. 错觉-Info:视错觉与UI元素间的可能

    ylbtech-错觉-Info:视错觉与UI元素间的可能 1.返回顶部 1. 视觉原理在当下红火的机械视觉中是必不可少的,那在我们日常工作的UI产品设计中又有什么可能性的呢?今天,我从“视错觉”这个角 ...

  6. myeclipse10 java builder path libraries 添加tomcat

    Error:     The import javax.servlet cannot be resolved     The import javax.servlet.http.HttpServlet ...

  7. 解决CSDN博客插入代码出现的问题

    我在写CSDN博客的时候有时候会在插入代码之后继续编辑,然后保存之后经常会出现一些多余的符号<p 例如<pre></pre>,这样的标记,其实这是html的一个元素,pr ...

  8. 一些windows server的操作

    windows server2008R2的一些操作和arcgis9.3 服务和arcgis9.3安装 1.在虚拟机中安装: https://jingyan.baidu.com/article/0eb4 ...

  9. IUAP--单点登录

    登录组件: 提供统一的登录组件 身份.证明验证身份 支持多种身份标识,用户名.邮箱.手机号 支持多个域,从与得到用户响应的角色,权限进行验证用户时候能进行操作. 支持会话管理和安全管理 支持多种验证策 ...

  10. laravel学习文档

    https://github.com/barryvdh/laravel-debugbar Laravel 精选资源大全 http://laravelacademy.org/post/153.html ...