BZOJ_1834_[ZJOI2010]network 网络扩容_费用流

时间:2022-10-01 13:29:12

BZOJ_1834_[ZJOI2010]network 网络扩容_费用流

题意:

给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求: 
1、在不扩容的情况下,1到N的最大流; 
2、将1到N的最大流增加K所需的最小扩容费用。
 
分析:
第一问直接最大流。
第二问我们对于每条边,连一个容量不变,费用为0的表示不花钱能通过一些流量
再连一个容量无限,费用为扩容费用的边表示要想扩容必须花钱
再限制最大流为k,新建源点,源点向1连容量为k的边
跑最小费用最大流即可。
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
#define N 2050
#define M 60050
#define inf 100000000
#define S (n+1)
#define T (n+2)
int head[N],to[M],nxt[M],flow[M],val[M],path[M],cnt=1;
int n,m,k,Q[N],l,r,dep[N],inq[N];
int xx[M],yy[M],cc[M],ww[M],dis[N];
inline void add1(int u,int v,int f)
{
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;flow[cnt]=f;
}
inline void add2(int u,int v,int f,int c)
{
to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;flow[cnt]=f;val[cnt]=c;
}
bool bfs()
{
memset(dep,0,sizeof(dep));
l=r=0;
dep[1]=1;
Q[r++]=1;
int i;
while(l^r)
{
int x=Q[l++];if(l==n+1)l=0;
for(i=head[x];i;i=nxt[i])if(!dep[to[i]]&&flow[i])
{
dep[to[i]]=dep[x]+1;
if(to[i]==n)return 1;
Q[r++]=to[i];if(r==n+1)r=0;
}
}
return 0;
}
int dfs(int x,int mf)
{
if(x==n)return mf;
int nf=0;
int i;
for(i=head[x];i;i=nxt[i])if(dep[to[i]]==dep[x]+1&&flow[i])
{
int tmp=dfs(to[i],min(flow[i],mf-nf));
nf+=tmp;
flow[i]-=tmp;
flow[i^1]+=tmp;
if(nf==mf)break;
}
dep[x]=0;
return nf;
}
bool spfa()
{
memset(dis,0x3f,sizeof(dis));
memset(path,0,sizeof(path));
l=r=0;
int i;
Q[r++]=S;dis[S]=0;inq[S]=1;
while(l^r)
{
int x=Q[l++];if(l==n+4)l=0;inq[x]=0;
for(i=head[x];i;i=nxt[i])
{
if(flow[i]>0&&dis[to[i]]>dis[x]+val[i])
{
dis[to[i]]=dis[x]+val[i];
path[to[i]]=i^1;
if(!inq[to[i]])
{
inq[to[i]]=1;
Q[r++]=to[i];
if(r==n+4)r=0;
}
}
}
}
return dis[T]<inf;
}
void mcmf()
{
int mnc=0,mxf=0,i;
while(spfa())
{
int nf=1<<30;
for(i=T;i!=S;i=to[path[i]])
{
nf=min(nf,flow[path[i]^1]);
}
for(i=T;i!=S;i=to[path[i]])
{
flow[path[i]]+=nf;
flow[path[i]^1]-=nf;
mnc+=val[path[i]^1]*nf;
}
mxf+=nf;
}
printf("%d\n",mnc);
}
void dinic()
{
int ans=0,f;
while(bfs())
{
while(f=dfs(1,inf))
ans+=f;
}
k+=ans;
printf("%d ",ans);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
int i;
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&xx[i],&yy[i],&cc[i],&ww[i]);
add1(xx[i],yy[i],cc[i]);
add1(yy[i],xx[i],0);
}
dinic();
cnt=1;
memset(head,0,sizeof(head));
add2(S,1,k,0);
add2(1,S,0,0);
add2(n,T,k,0);
add2(T,n,0,0);
for(i=1;i<=m;i++)
{
add2(xx[i],yy[i],cc[i],0);
add2(yy[i],xx[i],0,0);
add2(xx[i],yy[i],inf,ww[i]);
add2(yy[i],xx[i],0,-ww[i]);
}
mcmf();
}