【算法】网络流-最大流+最小费用最大流(费用流)

【题解】

第一问跑最大流。

第二问:

原始边相当于费用为0的边,再原图(跑过最大流的图)基础上添加带费用的边,容量为k(相当于inf)。

第一问最大流使用了哪条边对第二问没有影响,因为费用流肯定优先往费用为0的边(原始边)跑。

限流k?添加超级源向1连容量k费用0的边即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,maxm=,N=,inf=0x3f3f3f3f;
int tot=,first[maxn],d[maxn],q[maxn],cur[maxn],S,T,sum,n,m,K,u[maxm],v[maxm],w[maxm];
bool vis[maxn];
struct edge{int v,f,c,from;}e[maxm*]; void insert(int u,int v,int f,int c){
tot++;e[tot].v=v;e[tot].f=f;e[tot].c=c;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u;e[tot].f=;e[tot].c=-c;e[tot].from=first[v];first[v]=tot;
}
bool bfs(){
memset(d,-,sizeof(d));
int head=,tail=;q[head]=S;d[S]=;
while(head<tail){
int x=q[head++];
for(int i=first[x];i;i=e[i].from)
if(e[i].f&&d[e[i].v]==-){
d[e[i].v]=d[x]+;
q[tail++]=e[i].v;
}
}
return ~d[T];
}
int dinic(int x,int a){
if(x==T||a==)return a;
int flow=,f;
for(int& i=cur[x];i;i=e[i].from)
if(d[e[i].v]==d[x]+&&(f=dinic(e[i].v,min(e[i].f,a)))){
e[i].f-=f;e[i^].f+=f;
flow+=f;a-=f;
if(a==)break;
}
return flow;
}
int solve1(){
int ans=;
while(bfs()){
for(int i=S;i<=T;i++)cur[i]=first[i];
ans+=dinic(S,inf);
}
return ans;
}
bool spfa(){
memset(d,0x3f,sizeof(d));
int head=,tail=;q[head]=T;d[T]=;vis[T]=;
while(head!=tail){
int x=q[head++];if(head>N)head=;
for(int i=first[x];i;i=e[i].from)
if(e[i^].f&&d[x]+e[i^].c<d[e[i].v]){
d[e[i].v]=d[x]+e[i^].c;
if(!vis[e[i].v]){
if(d[e[i].v]<d[q[head]]){if(--head<)head=N;q[head]=e[i].v;}
else{q[tail++]=e[i].v;if(tail>N)tail=;}
vis[e[i].v]=;
}
}
vis[x]=;//
}
return d[S]<inf;
}
int dfs(int x,int a){
if(x==T||a==)return a;
vis[x]=;
int flow=,f;
for(int& i=cur[x];i;i=e[i].from)
if(!vis[e[i].v]&&d[e[i].v]+e[i].c==d[x]&&(f=dfs(e[i].v,min(e[i].f,a)))){
e[i].f-=f;e[i^].f+=f;
sum+=e[i].c*f;
flow+=f;a-=f;
if(a==)break;
}
vis[x]=;
return flow;
}
int solve2(){
sum=;
while(spfa()){
for(int i=S;i<=T;i++)cur[i]=first[i];
dfs(S,inf);
}
return sum;
}
int main(){
scanf("%d%d%d",&n,&m,&K);
S=;T=n;
for(int i=;i<=m;i++){
int c;
scanf("%d%d%d%d",&u[i],&v[i],&c,&w[i]);
insert(u[i],v[i],c,);
}
printf("%d ",solve1());
S=;
for(int i=;i<=m;i++)insert(u[i],v[i],K,w[i]);
insert(S,,K,);
printf("%d",solve2());
return ;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,maxm=,N=,inf=0x3f3f3f3f;
int tot=,first[maxn],d[maxn],q[maxn],cur[maxn],S,T,sum,n,m,K,u[maxm],v[maxm],w[maxm],c[maxm];
bool vis[maxn];
struct edge{int v,f,c,from;}e[maxm*]; void insert(int u,int v,int f,int c){
tot++;e[tot].v=v;e[tot].f=f;e[tot].c=c;e[tot].from=first[u];first[u]=tot;
tot++;e[tot].v=u;e[tot].f=;e[tot].c=-c;e[tot].from=first[v];first[v]=tot;
}
bool bfs(){
memset(d,-,sizeof(d));
int head=,tail=;q[head]=S;d[S]=;
while(head<tail){
int x=q[head++];
for(int i=first[x];i;i=e[i].from)
if(e[i].f&&d[e[i].v]==-){
d[e[i].v]=d[x]+;
q[tail++]=e[i].v;
}
}
return ~d[T];
}
int dinic(int x,int a){
if(x==T||a==)return a;
int flow=,f;
for(int& i=cur[x];i;i=e[i].from)
if(d[e[i].v]==d[x]+&&(f=dinic(e[i].v,min(e[i].f,a)))){
e[i].f-=f;e[i^].f+=f;
flow+=f;a-=f;
if(a==)break;
}
return flow;
}
int solve1(){
int ans=;
while(bfs()){
for(int i=S;i<=T;i++)cur[i]=first[i];
ans+=dinic(S,inf);
}
return ans;
}
bool spfa(){
memset(d,0x3f,sizeof(d));
int head=,tail=;q[head]=T;d[T]=;vis[T]=;
while(head!=tail){
int x=q[head++];if(head>N)head=;
for(int i=first[x];i;i=e[i].from)
if(e[i^].f&&d[x]+e[i^].c<d[e[i].v]){
d[e[i].v]=d[x]+e[i^].c;
if(!vis[e[i].v]){
if(d[e[i].v]<d[q[head]]){if(--head<)head=N;q[head]=e[i].v;}
else{q[tail++]=e[i].v;if(tail>N)tail=;}
vis[e[i].v]=;
}
}
vis[x]=;//
}
return d[S]<inf;
}
int dfs(int x,int a){
if(x==T||a==)return a;
vis[x]=;
int flow=,f;
for(int& i=cur[x];i;i=e[i].from)
if(!vis[e[i].v]&&d[e[i].v]+e[i].c==d[x]&&(f=dfs(e[i].v,min(e[i].f,a)))){
e[i].f-=f;e[i^].f+=f;
sum+=e[i].c*f;
flow+=f;a-=f;
if(a==)break;
}
vis[x]=;
return flow;
}
int solve2(){
sum=;
while(spfa()){
for(int i=S;i<=T;i++)cur[i]=first[i];
dfs(S,inf);
}
return sum;
}
int main(){
scanf("%d%d%d",&n,&m,&K);
S=;T=n;
for(int i=;i<=m;i++){
scanf("%d%d%d%d",&u[i],&v[i],&c[i],&w[i]);
insert(u[i],v[i],c[i],);
}
int now=;
printf("%d ",now=solve1());
tot=;memset(first,,sizeof(first));//
for(int i=;i<=m;i++){
insert(u[i],v[i],c[i],);
insert(u[i],v[i],K,w[i]);
}
S=;
insert(S,,now+K,);
printf("%d",solve2());
return ;
}

【BZOJ】1834 [ZJOI2010]network 网络扩容的更多相关文章

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

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

  2. bzoj 1834: [ZJOI2010]network 网络扩容 -- 最大流+费用流

    1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec  Memory Limit: 64 MB Description 给定一张有向图,每条边都有一个容量C和一 ...

  3. bzoj 1834 [ZJOI2010]network 网络扩容(MCMF)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1834 [题意] 给定一个有向图,每条边有容量C,扩容费用W,问最大流和使容量增加K的最 ...

  4. BZOJ 1834 [ZJOI2010]network 网络扩容(费用流)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1834 [题目大意] 给定一张有向图,每条边都有一个容量C和一个扩容费用W. 这里扩容费 ...

  5. bzoj 1834: [ZJOI2010]network 网络扩容

    #include<cstdio> #include<iostream> #include<cstring> #define M 100000 #define inf ...

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

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

  7. BZOJ 1834: [ZJOI2010]network 网络扩容 最小费用流_最大流_残量网络

    对于第一问,跑一遍最大流即可. 对于第二问,在残量网络上的两点间建立边 <u,v>,容量为无限大,费用为扩充费用. 跑一遍最小费用流即可. Code: #include <vecto ...

  8. BZOJ 1834: [ZJOI2010]network 网络扩容(网络流+费用流)

    一看就知道是模板题= = ,不说什么了= = PS:回去搞期末了,暑假再来刷题了 CODE: #include<cstdio> #include<iostream> #incl ...

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

    http://www.lydsy.com/JudgeOnline/problem.php?id=1834 我又思考人生了T_T,nd的数组开小了,一直wa,调了一个小时才发现啊!!!!!我一直以为我的 ...

随机推荐

  1. DS06--图

    一.学习总结 1.图的思维导图 2.图学习体会 深度优先遍历与广度优先遍历 不同点:广度优先搜索,适用于所有情况下的搜索,但是深度优先搜索不一定能适用于所有情况下的搜索.因为由于一个有解的问题树可能含 ...

  2. spring 整合 struts2 + Hibernate application配置文件(基于注解)

    下面是 application.xml 文件. <?xml version="1.0" encoding="UTF-8"?> <beans x ...

  3. js get selected text

    js get selected text https://stackoverflow.com/questions/3170648/how-to-get-javascript-select-boxs-s ...

  4. [BinaryTree] 二叉树常考知识点

    1.二叉树第i层至多有2^(i-1)个结点(i>=1). 2.深度为k的二叉树上,至多含2^k-1个结点(k>=1) 3.n0 = n2 + 1(度) 4.满二叉树:深度为k且含有2^k- ...

  5. 【bzoj3064】Tyvj 1518 CPU监控 线段树维护历史最值

    题目描述 给你一个序列,支持4种操作:1.查询区间最大值:2.查询区间历史最大值:3.区间加:4.区间赋值. 输入 第一行一个正整数T,表示Bob需要监视CPU的总时间. 然后第二行给出T个数表示在你 ...

  6. Luogu4926 倍杀测量者(二分答案+差分约束)

    容易想到二分答案.问题变为判断是否所有条件都被满足,可以发现这是很多变量间的相对关系,取个log之后就是经典的差分约束模型了.特殊的地方在于某些人的分数已被给定,从每个人开始跑一遍最短路判断一下是否能 ...

  7. NLP度量指标BELU真的完美么?

    摘要: NLP重要评价准则之一——BLEU,真的完美无缺么? 刚接触自然语言处理的朋友通常会问我:当系统的输出是文本,而非对输入文本进行某种分类,如何对该系统进行评估.当模型的输入是文本信息,输出也是 ...

  8. 【BZOJ4889】不勤劳的图书管理员(树套树)

    [BZOJ4889]不勤劳的图书管理员(树套树) 题面 又是权限题,烦死了 洛谷真好 题解 分开考虑每一次交换产生的贡献. 假设交换\((x,y)\) 检查\(x\)与\(y\)对于区间\([x+1, ...

  9. linux安全第二周学习总结

    一.实验过程 cd LinuxKernel/linux-3.9.4 qemu -kernel arch/x86/boot/bzImage 然后cd mykernel 您可以看到qemu窗口输出的内容的 ...

  10. 升级系统后maxvim不能用,重新下载编译个

    1. 获取macvim源代码git clone https://github.com/b4winckler/macvim.git 2 配置及编译 编译选项 ./configure --with-fea ...