BZOJ_1834_[ZJOI2010]network 网络扩容_费用流
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(); }