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

【题解】

第一问跑最大流。

第二问:

原始边相当于费用为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. adb使用过程常见的几种错误总结

    问题1:Failure [INSTALL_FAILED_ALREADY_EXISTS] 问题原因:该程序已存在. 解决方法:增加-r参数,即可成功覆盖安装 问题2:Failure [INSTALL_F ...

  2. 第138天:Web前端面试题总结(编程)

    1.如何让一个盒子水平垂直居中 //已知宽高 <div class="div1"></div> <style> .div1{ width:400 ...

  3. POJ3378_Crazy Thairs

    这个题目很有意思,也是一个很好的题目,涉及的知识点比较广,要求较高. 题目是这样的,给定你一个n个数的数列,问你有多少个长度为5的上升序列. 首先看到有50000,我们就知道肯定不会是DP.(但是不知 ...

  4. HDU4473_Exam

    很考验智商的一个题目,赛后看完别人的题解后秒懂了. 首先定义一个函数f(x)表示a,b的有序组合情况数使得a*b为x的一个约数. 现在给定你一个n,要你求出f(1)+f(2)+……+f(n): 题目智 ...

  5. CF486D-Valid Sets

    题目 给出一个\(n\)个点的树,每个点有权值\(a_i\),再给出一个\(d\),问有多少个非空点集满足: 点集在树上构成联通子图 \[\max _{v\in S}a_v -\min _{v\in ...

  6. BZOJ 2186 沙拉公主的困惑(预处理逆元+欧拉函数)

    题意:求1-n!里与m!互质的数有多少?(m<=n<=1e6). 因为n!%m!=0,所以题目实际上求的是phi(m!)*n!/m!. 预处理出这些素数的逆元和阶乘的模即可. # incl ...

  7. Java Servlet异步处理、非阻塞I/O和文件上传

    异步处理 应用服务器中的 web容器通常对各个客户端情求分别使用一个服务器线程.在工作负载很繁重的情况下,容器常要大量线程来为所有客户端请求服务.可扩展性限制包括内存用尽,或容器线程池耗尽.为了创建可 ...

  8. request之setAtrribute

    当在servlet中有request.SetAtrribute("AtriruteName",AtrributeValue)语句时,在jsp页面获取AtrributeValue有两 ...

  9. click()、bind()、live()和delegate()方法

    我之前使用click()比较多,又来因为网页内容需要前端生成用了live().有的时候使用click()和bind()分不清楚该怎么试用.查了很多资料.测试了很多次,自己明白了. 总结如下:代码注释很 ...

  10. [十五]SpringBoot 之 启动加载数据

    实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求. 为了解决这样的问题,spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunner 来 ...