1. 程式人生 > >[BZOJ 1834][ZJOI2010]network 網絡擴容(費用流)

[BZOJ 1834][ZJOI2010]network 網絡擴容(費用流)

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 網絡擴容(費用流)