题目链接:https://www.luogu.org/problem/P2604

题目描述

给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

解题思路:

1.对于1,直接跑一遍最大流即可, 费用设为 0 。

2.对于2,在跑完最大流后的残留网络上加边,对每条边加上容量为 inf, 费用为边的扩容费用。这样保证费用是正确的,为了保证扩容为k,加一个源点0,容量为k,费用为 0 ,连向1点。跑最小费用(0,n)即可。

3.思考为什么可以在残留网络上加边,因为边的费用不是单位流量费用,而是扩容费用。对一条已经满流的边扩容即可增加其他未满流的边的流量,这时其他边的费用是0,因为并没有扩容。在其他边也满流之后,扩容才需要费用,也才会用到所加的inf的边(因为残留网络

上费用为0,会优先用)

代码:

 #include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int MAXM = ;
const int MAXN = ;
const int inf = 0x3f3f3f3f; int n, m, k; //n个点 m条有向边, 扩容k
queue<int> Q;
int dep[MAXN], last[MAXN], pre[MAXN], dis[MAXN], flow[MAXN], vis[MAXN]; struct Node
{
int a, b, c, d;
}no[MAXM];
int tot; struct Edge
{
int to, next, flow, dis;
}edge[ * MAXN];
int head[MAXN], cnt; void add(int a, int b, int c, int d)
{
edge[++ cnt].to = b;
edge[cnt].next = head[a];
edge[cnt].flow = c;
edge[cnt].dis = d;
head[a] = cnt;
} int spfa(int st, int ed)
{
while(!Q.empty())
Q.pop();
mem(vis, ), mem(flow, inf), mem(dis, inf), pre[ed] = -;
dis[st] = ;
vis[st] = ;
Q.push(st);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
vis[now] = ;
for(int i = head[now]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(edge[i].flow > && dis[to] > dis[now] + edge[i].dis)
{
dis[to] = dis[now] + edge[i].dis;
last[to] = i;
pre[to] = now;
flow[to] = min(flow[now], edge[i].flow);
if(!vis[to])
{
vis[to] = ;
Q.push(to);
}
}
}
}
return pre[ed] != -;
} int min_cost, max_flow;
void MCMF(int st, int ed)
{
min_cost = ;
max_flow = ;
while(spfa(st, ed))
{
int now = ed;
min_cost += flow[ed]*dis[ed];
max_flow += flow[ed];
while(now != st)
{
edge[last[now]].flow -= flow[ed];
edge[last[now] ^ ].flow += flow[ed];
now = pre[now];
}
}
} int main()
{
scanf("%d%d%d", &n, &m, &k);
mem(head, -), cnt = -, tot = ;
for(int i = ; i <= m; i ++)
{
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
no[i].a = a, no[i].b = b, no[i].c = c, no[i].d = d; //把输入的边记录下来
add(a, b, c, );
add(b, a, , );
}
MCMF(,n);
printf("%d ",max_flow);
for(int i = ; i <= m; i ++) //在残留网络上加边 边的容量为 inf 费用为d
{
add(no[i].a, no[i].b, inf, no[i].d);
add(no[i].b, no[i].a, , -no[i].d);
}
add(, , k, );//加一个新的源点 0,容量为需要扩容的k,费用为 0。这样跑满流一定是k。
add(, , , );
MCMF(,n);
printf("%d\n", min_cost);
return ;
}

洛谷P2604 最大流+最小费用最大流的更多相关文章

  1. 洛谷 P4015 运输问题 【最小费用最大流+最大费用最大流】

    s向仓库i连ins(s,i,a[i],0),商店向t连ins(i+m,t,b[i],0),商店和仓库之间连ins(i,j+m,inf,c[i][j]).建两次图分别跑最小费用最大流和最大费用最大流即可 ...

  2. 洛谷 P4014 分配问题 【最小费用最大流+最大费用最大流】

    其实KM更快--但是这道题不卡,所以用了简单粗暴的费用流,建图非常简单,s向所有人连流量为1费用为0的边来限制流量,所有工作向t连流量为1费用为0的边,然后对应的人和工作连(i,j,1,cij),跑一 ...

  3. 【洛谷 p3381】模板-最小费用最大流(图论)

    题目:给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 解法:在Dinic的基础下做spfa算法. 1 #include<cst ...

  4. BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)

    第一问直接跑最大流.然后将所有边再加一次,费用为扩容费用,容量为k,再从一个超级源点连一条容量为k,费用为0的边到原源点,从原汇点连一条同样的边到超级汇点,然  后跑最小费用最大流就OK了. ---- ...

  5. bzoj 1834: [ZJOI2010]network 网络扩容【最大流+最小费用最大流】

    第一问直接跑最大流即可.建图的时候按照费用流建,费用为0. 对于第二问,在第一问dinic剩下的残量网络上建图,对原图的每条边(i,j),建(i,j,inf,cij),表示可以用c的花费增广这条路.然 ...

  6. 最大流 && 最小费用最大流模板

    模板从  这里   搬运,链接博客还有很多网络流题集题解参考. 最大流模板 ( 可处理重边 ) ; const int INF = 0x3f3f3f3f; struct Edge { int from ...

  7. [模板]网络最大流 & 最小费用最大流

    我的作业部落有学习资料 可学的知识点 Dinic 模板 #define rg register #define _ 10001 #define INF 2147483647 #define min(x ...

  8. POJ - 2516 Minimum Cost(最小费用最大流)

    1.K种物品,M个供应商,N个收购商.每种物品从一个供应商运送到一个收购商有一个单位运费.每个收购商都需要K种物品中的若干.求满足所有收购商需求的前提下的最小运费. 2.K种物品拆开来,分别对每种物品 ...

  9. 洛谷P4014 分配问题【最小/大费用流】题解+AC代码

    洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...

随机推荐

  1. MySQL percona-toolkit工具详解

    一.检查和安装与Perl相关的模块 PT工具是使用Perl语言编写和执行的,所以需要系统中有Perl环境. 依赖包检查命令为: rpm -qa perl-DBI perl-DBD-MySQL perl ...

  2. MySQL Data Directory -- Creating file-per-table tablespaces outside the data directory

    Creating file-per-table tablespaces outside the data directory 一. Data Directory 1.应对情况 当数据库所在空间不足的时 ...

  3. crm-权限管理

    1 用户登录 设置session 将权限存放在session中 2 设置中间件,进行拦截 0 添加白名单,判断是否在白名单上 1 判断是否登录 2 权限过滤

  4. 【概率论】4-1:随机变量的期望(The Expectation of a Random Variable Part I)

    title: [概率论]4-1:随机变量的期望(The Expectation of a Random Variable Part I) categories: - Mathematic - Prob ...

  5. windows下注册表脚本编写

    Reg文件就是我今天所说的注册表脚本文件,双击可将其中的数据写入注册表.利用注册表脚本文件可以对注册表进行关于键值的任何操作,而且还不受注册表被禁用的限制.     我们平常对注册表的修改大体上可以分 ...

  6. Echarts案例-折线图

    一:先在官网下载 https://www.echartsjs.com/zh/download.html 然后再建立工程,导入这两个包: 写代码: <!DOCTYPE html> <h ...

  7. 利用python获取自己的qq群成员信息

    利用python获取自己的qq群成员信息! 首先说明一下需要使用的工具以及技术:python3 + selenium selenium安装方法:pip install selenium 前提:获取自己 ...

  8. 通过Vagrant搭建PHP环境(一) Vagrant box添加配置

    系统Windows10 Vagrant 1.8.1 VirtualBox 5.0.20 vagrant box下载地址:http://cloud.centos.org/centos/7/vagrant ...

  9. The first one spawns an additional process forwarding requests to a series of workers (think about it as a form of shield, at the same level of apache or nginx), while the second one sets workers to n

    Things to know (best practices and “issues”) READ IT !!! — uWSGI 2.0 documentationhttps://uwsgi-docs ...

  10. Clock Generator PLL with Integrated VCO_ADF4360-9

    Clock Generator PLL with Integrated VCO_ADF4360-9     2和3之间需要有大于15ms的时间间隔