[BZOJ 1834][ZJOI2010]network 網絡擴容(費用流)
阿新 • • 發佈:2017-05-17
bool ron return ins set esc -s main turn
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; }
[BZOJ 1834][ZJOI2010]network 網絡擴容(費用流)