题目链接: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. 003_软件安装之_Visual Studio 2012

    Visual Studio 2012安装,里面有视频教程,还有秘钥,连接失效联系我 2012版: 链接:https://pan.baidu.com/s/1BRE46cTKJW58YZ3lBFyjMw ...

  2. 006_STM32程序移植之_SYN6288语音模块

    1. 测试环境:STM32C8T6 2. 测试模块:SYN6288语音模块 3. 测试接口: SYN6288语音模块: VCC------------------3.3V GND----------- ...

  3. 2018-2019 ACM-ICPC, China Multi-Provincial Collegiate Programming Contest

    目录 Contest Info Solutions A. Maximum Element In A Stack B. Rolling The Polygon C. Caesar Cipherq D. ...

  4. CF915E 动态开线段树

    CF915E 动态开线段树 题面 因为\(n\le10^9\),所以动态开点,线段树维护\([1,n]\)天非工作日数量. 之前的结构体写法被卡了,只能改成函数传l,r(虽然也不难) 动态开点好写,但 ...

  5. luogu P1553 数字反转(升级版)

    P1553 数字反转(升级版) 直通 思路: 首先使用char数组进行读入,然后直接按照题目要求进行反转即可, 但要注意的是对零的处理:(有点类似于高精去除前导零) ①去除只是整数.百分数的时候,反转 ...

  6. 【概率论】4-4:距(Moments)

    title: [概率论]4-4:距(Moments) categories: - Mathematic - Probability keywords: - Moments - Moments Gene ...

  7. 畅通工程续(HDU 1874)(简单最短路)

    某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰. 现在 ...

  8. selenium 定制启动chrome的参数

    selenium 定制启动chrome的参数 设置代理. 禁止图片加载 修改ua https://blog.csdn.net/vinson0526/article/details/51850929 1 ...

  9. maven项目无法查看类库的源码

    一个Maven项目有两种类库,分别是JRE System Libaray和Maven Dependencies. JRE System Libaray 一般有两种方法指定. 1.由pom.xml中的m ...

  10. POJ 3616 Milking Time ——(记忆化搜索)

    第一眼看是线段交集问题,感觉不会= =.然后发现n是1000,那好像可以n^2建图再做.一想到这里,突然醒悟,直接记忆化搜索就好了啊..太蠢了.. 代码如下: #include <stdio.h ...