算法问题描述
在网络流的基础上,每条边有一个单位流量代价,要求最大流的情况下的最小费用流
SPFA流
算法思想
显然我们可以通过跑最短路找出一条流量一定下的费用最小的增光路,增广过程中和常规最大流不同的仅仅是建反向边时,反向边的代价是负值,保证代价可以回退。因为有负权,所以我们选择SPFA实现
代码
bool SPFA(int s,int t){
memset(dis,0x3f,sizeof(dis));
memset(minf,0x3f,sizeof(minf));
memset(vis,0,sizeof(vis));
queue<int> Q;
Q.push(s);
vis[s]=1;
dis[s]=0;
while(!Q.empty()){
int u=Q.front(); Q.pop(); vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v,c=edge[i].cost,f=edge[i].flow;
if(dis[u]+c<dis[v] && f){
dis[v]=dis[u]+c;
p[v]=i;
minf[v]=min(minf[u],f);
if(!vis[v]){
Q.push(v);
vis[v]=1;
}
}
}
}
return minf[t]!=INF;
}
void maxflow(int s,int t,LL& ans_flow,LL& ans_cost){
while(SPFA(s,t)){
int df=minf[t],x=t;
ans_flow+=df;
ans_cost+=dis[t]*df;
while(x!=s){
edge[p[x]].flow-=df;
edge[p[x]^1].flow+=df;
x=edge[p[x]].u;
}
}
}
zkw流
待填坑
Dijstra流
待填坑