費用流模板——EK+SPFA實現的最小費用最大流
阿新 • • 發佈:2019-01-27
演算法原理
用兩個字的高度概括——貪心~
用一句話的概括:每一次通過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;
}