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

【题解】

第一问跑最大流。

第二问:

原始边相当于费用为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. [codecademy]fonts in css

    Great job! You learned how to style an important aspect of the user experience: fonts! Let's review ...

  2. (一)Tensorflow安装

    主要包括下面两个指令: $ sudo apt-get install python-pip python-dev $ sudo pip install --upgrade https://storag ...

  3. vsftpd 安全性能工具

    vsftpd实战(服务端192.168.23.12,客户端192.168.23.11) 1:安装vsftpdyum install -y vsftpd 2:客户端安装lftpyum install - ...

  4. 1."问吧APP"客户需求调查分析

    产品名称:问吧 产品功能:实时提问回答和搜索 开发原因:任何人都会遇到问题,网上虽然有很多回答,但是互联网的信息错综复杂,开发这个APP就是为了让网络求助更加的合理有效,清除网络上的垃圾信息. 为知大 ...

  5. QUdpSocket-Qt使用Udp通讯实现服务端和客户端

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QUdpSocket-Qt使用Udp通讯实现服务端和客户端     本文地址:https:// ...

  6. TeamCity编译执行selenium上传窗口脚本缺陷

    2015-07-04 18:05 编写本文 TeamCity编译selenium脚本,对于上传窗口处理只支持sendKeys的使用,不支持模拟人为按下Enter键和使用autoIt等操作,即使本地调试 ...

  7. linux之JDK安装

    1.JDK安装 a.卸载JDK (1)卸载默认的JDK 用root用户登陆到系统,打开一个终端输入 # rpm -qa|grep gcj 显示内容其中包含下面两行信息 # java-1.4.2-gcj ...

  8. web.py 中文模版报错

    1. 作为模板的html文件,必须是utf-8编码; 2. html文件内容中的charset必须为utf-8,也就是必须包含 <meta http-equiv="Content-Ty ...

  9. 【bzoj5028】小Z的加油店 扩展裴蜀定理+差分+线段树

    题目描述 给出 $n$ 个瓶子和无限的水,每个瓶子有一定的容量.每次你可以将一个瓶子装满水,或将A瓶子内的水倒入B瓶子中直到A倒空或B倒满.$m$ 次操作,每次给 $[l,r]$ 内的瓶子容量增加 $ ...

  10. OEM SLP Key

    OEM SLP Key Windows Server 2012 R2 Datacenter ===================== 2N9T6-Y284D-T68G9-QGV6X-FRFTD -- ...