最小费用最大流模板
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。 输入输出格式 输入格式: 第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。 接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。 输出格式: 一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。 输入输出样例 输入样例#1: 4 5 4 3 4 2 30 2 4 3 20 3 2 3 20 1 2 1 30 9 1 3 40 5 输出样例#1: 50 280 说明 时空限制:1000ms,128M (BYX:最后两个点改成了1200ms) 数据规模: 对于30%的数据:N<=10,M<=10 对于70%的数据:N<=1000,M<=1000 对于100%的数据:N<=5000,M<=50000
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e5+10; struct node{ int u,v,fl,c,ne; }e[N*2]; int h[N],tot,n,m; void add1(int u,int v,int fl,int c) { tot++;e[tot]=(node){u,v,fl,c,h[u]};h[u]=tot; } void add(int u,int v,int fl,int c) { add1(u,v,fl,c);add1(v,u,0,-c); } queue<int>q; int d[N],S,T,pre[N],v[N]; bool spfa() { for(int i=1;i<=n;++i) d[i]=1e9,pre[i]=0,v[i]=0; d[S]=0;q.push(S);v[S]=1; while(!q.empty()) { int ff=q.front();q.pop();v[ff]=0; for(int i=h[ff];i;i=e[i].ne) { int rr=e[i].v; if(e[i].fl && d[rr]>d[ff]+e[i].c) { d[rr]=d[ff]+e[i].c;pre[rr]=i; if(!v[rr]) q.push(rr),v[rr]=1; } } } return d[T]<1e9; } int main() { scanf("%d%d%d%d",&n,&m,&S,&T); tot=1; for(int i=1,x,y,z,w;i<=m;++i) { scanf("%d%d%d%d",&x,&y,&w,&z); add(x,y,w,z); } ll ans1=0,ans2=0; while(spfa()) { int Min=1e9; for(int i=T;i!=S;i=e[pre[i]].u) Min=min(Min,e[pre[i]].fl); for(int i=T;i!=S;i=e[pre[i]].u) e[pre[i]].fl-=Min,e[pre[i]^1].fl+=Min; ans1+=Min;ans2+=1ll*Min*d[T]; } cout<<ans1<<" "<<ans2; return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=1e5+10; 5 struct node{ 6 int u,v,fl,c,ne; 7 }e[N*2]; 8 int h[N],tot,n,m; 9 void add1(int u,int v,int fl,int c) 10 { 11 tot++;e[tot]=(node){u,v,fl,c,h[u]};h[u]=tot; 12 } 13 void add(int u,int v,int fl,int c) 14 { 15 add1(u,v,fl,c);add1(v,u,0,-c); 16 } 17 queue<int>q; 18 int d[N],S,T,H[N],v[N]; 19 bool spfa() 20 { 21 for(int i=1;i<=n;++i) d[i]=1e9,v[i]=0; 22 d[S]=0;q.push(S);v[S]=1; 23 while(!q.empty()) 24 { 25 int ff=q.front();q.pop();v[ff]=0; 26 for(int i=h[ff];i;i=e[i].ne) 27 { 28 int rr=e[i].v; 29 if(e[i].fl && d[rr]>d[ff]+e[i].c) 30 { 31 d[rr]=d[ff]+e[i].c; 32 if(!v[rr]) q.push(rr),v[rr]=1; 33 } 34 } 35 } 36 return d[T]<1e9; 37 } 38 int dfs(int u,int fl) 39 { 40 v[u]=1; 41 if(u==T || fl==0) return fl; 42 int get=0,f; 43 for(int i=H[u];i;i=e[i].ne) 44 { 45 int rr=e[i].v; 46 if(e[i].fl && d[rr]==d[u]+e[i].c && !v[rr]) 47 { 48 f=dfs(rr,min(fl,e[i].fl)); 49 if(!f) continue; 50 get+=f;fl-=f; 51 e[i].fl-=f;e[i^1].fl+=f; 52 H[u]=i; 53 if(fl==0) break; 54 } 55 } 56 if(get==0) d[u]=1e9; 57 return get; 58 } 59 int main() 60 { 61 scanf("%d%d%d%d",&n,&m,&S,&T); 62 tot=1; 63 for(int i=1,x,y,z,w;i<=m;++i) 64 { 65 scanf("%d%d%d%d",&x,&y,&w,&z); 66 add(x,y,w,z); 67 } 68 ll ans1=0,ans2=0; 69 while(spfa()) 70 { 71 v[T]=1; 72 while(v[T]) 73 { 74 for(int i=1;i<=n;++i) H[i]=h[i],v[i]=0; 75 int nw=dfs(S,1e9); 76 ans1+=nw;ans2+=d[T]*nw; 77 } 78 } 79 cout<<ans1<<" "<<ans2; 80 return 0; 81 }