BZOJ 1834 [ZJOI2010]network 网络扩容(费用流)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1834
【题目大意】
给定一张有向图,每条边都有一个容量C和一个扩容费用W。
这里扩容费用是指将容量扩大1所需的费用。求:
1.在不扩容的情况下,1到N的最大流;
2.将1到N的最大流增加K所需的最小扩容费用。
【题解】
对于第一问,直接计算最大流即可,对于第二问,在最大流的残余网络上
对于每条边建立费用为w容量无限的边,跑1到N的流量大小为k的费用流即可。
【代码】
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <cstring> #include <queue> using namespace std; const int INF=0x3f3f3f3f; struct edge{int to,cap,cost,rev;}; const int MAX_V=10000; int V,dist[MAX_V],prevv[MAX_V],preve[MAX_V]; int level[MAX_V],iter[MAX_V]; vector<edge> G[MAX_V]; void add_edge(int from,int to,int cap,int cost){ G[from].push_back((edge){to,cap,cost,G[to].size()}); G[to].push_back((edge){from,0,-cost,G[from].size()-1}); } void bfs(int s){ memset(level,-1,sizeof(level)); queue<int> que; level[s]=0; que.push(s); while(!que.empty()){ int v=que.front(); que.pop(); for(int i=0;i<G[v].size();i++){ edge &e=G[v][i]; if(e.cap>0&&level[e.to]<0){ level[e.to]=level[v]+1; que.push(e.to); } } } } int dfs(int v,int t,int f){ if(v==t)return f; for(int &i=iter[v];i<G[v].size();i++){ edge &e=G[v][i]; if(e.cap>0&&level[v]<level[e.to]){ int d=dfs(e.to,t,min(f,e.cap)); if(d>0){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } }return 0; } int max_flow(int s,int t){ int flow=0; for(;;){ bfs(s); if(level[t]<0)return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,INF))>0){ flow+=f; } } } int min_cost_flow(int s,int t,int f){ int res=0; while(f>0){ fill(dist,dist+V,INF); dist[s]=0; bool update=1; while(update){ update=0; for(int v=0;v<V;v++){ if(dist[v]==INF)continue; for(int i=0;i<G[v].size();i++){ edge &e=G[v][i]; if(e.cap>0&&dist[e.to]>dist[v]+e.cost){ dist[e.to]=dist[v]+e.cost; prevv[e.to]=v; preve[e.to]=i; update=1; } } } } if(dist[t]==INF)return -1; int d=f; for(int v=t;v!=s;v=prevv[v]){ d=min(d,G[prevv[v]][preve[v]].cap); }f-=d; res+=d*dist[t]; for(int v=t;v!=s;v=prevv[v]){ edge &e=G[prevv[v]][preve[v]]; e.cap-=d; G[v][e.rev].cap+=d; } }return res; } void clear(){for(int i=0;i<V;i++)G[i].clear();} int N,M,K; int cas=0,a[5010],b[5010],c[5010],w[5010]; void solve(){ V=N+1; clear(); for(int i=1;i<=M;i++)add_edge(a[i],b[i],c[i],0); printf("%d ",max_flow(1,N)); for(int i=1;i<=M;i++)add_edge(a[i],b[i],INF,w[i]); printf("%d\n",min_cost_flow(1,N,K)); } int main(){ while(~scanf("%d%d%d",&N,&M,&K)){ for(int i=1;i<=M;i++)scanf("%d%d%d%d",&a[i],&b[i],&c[i],&w[i]); solve(); }return 0; }
愿你出走半生,归来仍是少年