最大流:
不断搜索增广路,寻找最小的容量-流量,得到最大流量,但最大流量在有花费时不一定是最小花费。
最小费用最大流
算法思想:
采用贪心的思想,每次找到一条从源点到达汇点的花费最小的路径,增加流量,直到无法找到一条从源点到达汇点的路径,算法结束。
由于最大流量有限,每执行一次循环流量都会增加,因此该算法肯定会结束,且同时流量也必定会达到网络的最大流量;同时由于每次都是增加的最小的花费,即当前的最小花费是所有到达当前流量flow时的花费最小值,因此最后的总花费最小。
附上洛谷P3381模板题:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 7 const int INF=0x7f7f7f7f; 8 const int MAXN=100000; 9 10 struct Edge 11 { 12 int u,v,w,c,next;//u起点,v终点,w容量,c花费,next下一条边 13 }E[MAXN]; 14 int node,head[MAXN]; 15 int pre[MAXN],cost[MAXN],vis[MAXN]; 16 int s,t; 17 int n,m,ans1,ans2; 18 19 void insert(int u,int v,int w,int c) 20 { 21 E[++node]=(Edge){u,v,w,c,head[u]}; 22 head[u]=node; 23 E[++node]=(Edge){v,u,0,-c,head[v]}; 24 head[v]=node; 25 } 26 27 bool spfa() 28 { 29 queue<int> Q; 30 memset(cost,0x7f,sizeof(cost)); 31 Q.push(s); 32 cost[s]=0;vis[s]=1; 33 while(!Q.empty()) 34 { 35 int q=Q.front();Q.pop(); 36 for(int i=head[q];i;i=E[i].next) 37 if(E[i].w&&cost[q]+E[i].c<cost[E[i].v]) 38 { 39 cost[E[i].v]=cost[q]+E[i].c; 40 pre[E[i].v]=i; 41 if(!vis[E[i].v]) 42 { 43 Q.push(E[i].v); 44 vis[E[i].v]=1; 45 } 46 } 47 vis[q]=0; 48 } 49 return cost[t]!=INF; 50 } 51 52 void mcf() 53 { 54 int minn=INF; 55 for(int i=pre[t];i;i=pre[E[i].u]) 56 minn=min(minn,E[i].w); 57 for(int i=pre[t];i;i=pre[E[i].u]) 58 { 59 ans2+=minn*E[i].c; 60 E[i].w-=minn; 61 E[i^1].w+=minn; 62 } 63 ans1+=minn; 64 } 65 66 int main() 67 { 68 scanf("%d%d%d%d",&n,&m,&s,&t); 69 for(int i=1;i<=m;i++) 70 { 71 int u,v,w,c; 72 scanf("%d%d%d%d",&u,&v,&w,&c); 73 insert(u,v,w,c); 74 } 75 while(spfa()) mcf(); 76 printf("%d %d",ans1,ans2);//ans1最大流 ans2最小费用 77 return 0; 78 }