BZOJ 1834: [ZJOI2010]network 网络扩容 最小费用流_最大流_残量网络
对于第一问,跑一遍最大流即可.
对于第二问,在残量网络上的两点间建立边 <u,v>,容量为无限大,费用为扩充费用.
跑一遍最小费用流即可.
Code:
#include <vector> #include <cstdio> #include <queue> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define inf 100000000 #define maxn 100000 #define ll long long using namespace std; struct Edges{ int u,v,c,w; }EDGE[maxn]; int n,m,k,s,t; struct Edge{ int from,to,cap,cost; Edge(int u,int v,int c,int f) : from(u),to(v),cap(c),cost(f){} }; vector<int>G[maxn]; vector<Edge>edges; void addedge(int u,int v,int c,int f){ edges.push_back(Edge(u,v,c,f)); edges.push_back(Edge(v,u,0,-f)); int o = edges.size(); G[u].push_back(o - 2); G[v].push_back(o - 1); } namespace Dinic{ int d[maxn],vis[maxn]; queue<int>Q; int BFS(){ memset(vis,0,sizeof(vis)); vis[s] = 1,d[s] = 0; Q.push(s); while(!Q.empty()){ int u = Q.front(); Q.pop(); int sz = G[u].size(); for(int i=0;i<sz;++i) { Edge r = edges[G[u][i]]; if(!vis[r.to] && r.cap > 0) { d[r.to] = d[u] + 1; vis[r.to] = 1; Q.push(r.to); } } } return vis[t]; } int current[maxn]; int DFS(int x,int cur){ if(x==t) return cur; int flow=0,f; int sz = G[x].size(); for(int i=current[x];i<sz;++i) { int u = G[x][i]; Edge r = edges[u]; if(d[r.to] == d[x] + 1 && r.cap > 0){ f = DFS(r.to,min(cur,r.cap)); if(f > 0) { flow += f; cur -= f; edges[u].cap -= f; edges[u^1].cap += f; } } if(cur==0) break; } return flow; } int maxflow(){ int flow=0; while(BFS()){ memset(current,0,sizeof(current)); flow += DFS(s,inf); } return flow; } }; namespace MCMF{ queue<int>Q; int d[maxn],inq[maxn]; int flow2[maxn],a[maxn]; long long ans; int SPFA(){ for(int i=0;i<maxn;++i) d[i] = flow2[i] = inf; memset(inq,0,sizeof(inq)); inq[s] = 1; d[s] = 0; Q.push(s); while(!Q.empty()){ int u=Q.front();Q.pop(); inq[u] = 0; int sz = G[u].size(); for(int i=0;i<sz;++i) { Edge r = edges[G[u][i]]; if(r.cap > 0 && d[r.to] > d[u] + r.cost) { d[r.to] = d[u] + r.cost; a[r.to] = G[u][i]; flow2[r.to] = min(flow2[u],r.cap); if(!inq[r.to]) { inq[r.to] = 1; Q.push(r.to); } } } } if(flow2[t] == inf) return 0; int f = flow2[t]; edges[a[t]].cap -= f, edges[a[t] ^ 1].cap += f; int u = edges[a[t]].from; while(u != s){ edges[a[u]].cap -= f; edges[a[u]^1].cap += f; u = edges[a[u]].from; } ans += (ll)(d[t] * f); return 1; } long long getcost(){ while(SPFA()); return ans; } }; int main(){ //setIO("input"); scanf("%d%d%d",&n,&m,&k); s = 1, t = n; for(int i = 1;i <= m; ++i) scanf("%d%d%d%d",&EDGE[i].u,&EDGE[i].v,&EDGE[i].c,&EDGE[i].w); for(int i = 1;i <= m; ++i) addedge(EDGE[i].u,EDGE[i].v,EDGE[i].c,0); printf("%d ",Dinic::maxflow()); for(int i = 1;i <= m; ++i) addedge(EDGE[i].u,EDGE[i].v,inf,EDGE[i].w); s = 0 , t = n + 1; addedge(s,1,k,0); addedge(n,n+1,k,0); printf("%lld",MCMF::getcost()); return 0; }