[BZOJ 1834][ZJOI2010]network 网络扩容(费用流)
Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
Solution
先求出最大流maxflow
求最小扩容费用的话,对于每一条边,建一条容量为c费用为0的边,再建一条容量为INF费用为w的边
跑费用流求流入maxflow+k的费用
#include<iostream> #include<cstdio> #include<queue> #include<cstdlib> #include<cstring> #define INF 0x3f3f3f3f using namespace std; int s,t,n,m,k,head[1005],cnt=0,a[1005],dis[1005],pre[1005]; int flow,cost; bool inq[1005]; int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-'0';c=getchar(); } return x*f; } struct Node { int next,from,to,cap,w; }Edges[20005]; void addedge(int u,int v,int c,int w) { Edges[cnt].next=head[u]; head[u]=cnt; Edges[cnt].from=u; Edges[cnt].to=v; Edges[cnt].cap=c; Edges[cnt].w=w; cnt++; } void insert(int u,int v,int c,int w) { addedge(u,v,c,w); addedge(v,u,0,-w); } queue<int>q; void MCMF(int x) { flow=0,cost=0; while(1) { memset(a,0,sizeof(a)); memset(dis,0x3f,sizeof(dis)); q.push(s); pre[s]=-1;dis[s]=0,a[s]=x?x-flow:INF,inq[s]=1; while(!q.empty()) { int u=q.front(); q.pop(),inq[u]=0; for(int i=head[u];~i;i=Edges[i].next) { int v=Edges[i].to; if(!x&&Edges[i].cap==INF)continue; if(dis[v]>dis[u]+Edges[i].w&&Edges[i].cap>0) { dis[v]=dis[u]+Edges[i].w; a[v]=min(a[u],Edges[i].cap); pre[v]=i; if(!inq[v]){q.push(v);inq[v]=1;} } } } if(a[t]==0)break; flow+=a[t]; int p=t; cost+=a[t]*dis[t]; while(pre[p]!=-1) { Edges[pre[p]].cap-=a[t]; Edges[pre[p]^1].cap+=a[t]; p=Edges[pre[p]].from; } } } int main() { memset(head,-1,sizeof(head)); n=read(),m=read(),k=read(); s=1,t=n; for(int i=1;i<=m;i++) { int u=read(),v=read(),c=read(),w=read(); insert(u,v,c,0); insert(u,v,INF,w); } MCMF(0); printf("%d ",flow); MCMF(k); printf("%d\n",cost); return 0; }