1. 程式人生 > >費用流模板——EK+SPFA實現的最小費用最大流

費用流模板——EK+SPFA實現的最小費用最大流

演算法原理

用兩個字的高度概括——貪心~
用一句話的概括:每一次通過spfa找到花費最小的可行流,然後進行增廣,直到殘量網路中,源點不能達到匯點。
其實還是通過程式碼理解比較好。

code

這裡1是源點,n是匯點。
每次的讀入四個數:有向邊的兩個結點+容量+費用

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    int num=0;char c=' ';bool flag=true;
    for(;c>'9'||c<'0';c=getchar())
        if
(c=='-') flag=false; for(;c>='0'&&c<='9';num=(num<<3)+(num<<1)+c-48,c=getchar()); return flag ? num : -num; } namespace graph{ const int maxn=20000; const int N=500; struct node{ int y,val,next,cost; }a[maxn<<1]; int head[N],top=0
; void insert(int x,int y,int v,int c){ a[top].y=y; a[top].val=v; a[top].next=head[x]; a[top].cost=c; head[x]=top++; } int n,m,s,t; void init(){ memset(head,-1,sizeof head); n=read();m=read(); s=1;t=n; for(int i=1
;i<=m;i++){ int x=read(); int y=read(); int v=read(); int c=read(); insert(x,y,v,c); insert(y,x,0,-c); } } }using namespace graph; namespace max_flow{ int pre[N],dis[N],flow[N],maxflow=0,mincost=0; bool vis[N]; bool spfa(){ memset(dis,0x7f,sizeof dis); memset(vis,0,sizeof vis); queue<int>q; q.push(s); vis[s]=true; dis[s]=0; flow[s]=0x7f7f7f7f; while(q.size()){ int u=q.front(); vis[u]=false; q.pop(); for(int i=head[u];i+1;i=a[i].next){ if(a[i].val==0)continue; int v=a[i].y; flow[v]=min(a[i].val,flow[u]); if(dis[v]>dis[u]+a[i].cost){ dis[v]=dis[u]+a[i].cost; pre[v]=i; if(!vis[v]){ vis[v]=true; q.push(v); } } } } if(dis[t]==0x7f7f7f7f)return false; return true; } void updata(){ int x=t; while(x!=s){ int i=pre[x]; a[i].val-=flow[t]; a[i^1].val+=flow[t]; x=a[i^1].y; } maxflow+=flow[t]; mincost+=dis[t]*flow[t]; } }using namespace max_flow; int main(){ init(); while(spfa())updata(); printf("%d %d\n",maxflow,mincost); return 0; }