1. 程式人生 > >2018.06.27最小費用最大流模板

2018.06.27最小費用最大流模板

最小費用最大流是指整個容量網路在保證流量最大的情況下使花費的費用最小,所以說與求最大流的思想有所差異。

我們知道,求最大流的思想是每次找一條增廣路進行貪心直到貪不動為止,但是對於最小費用最大流這個問題來說,我們最後求得的一定是最大流,因此我們仍然每次貪心,只需保證費用最小即可。

於是我們使用SPFASPFA而不是bfsbfs來找最短增廣路,我們在進行SPFASPFA演算法的同時用一個predpred的陣列來記錄對於當前節點uu,從s>us->u路徑上離uu最近的點,即uu的前驅,最後從tt開始沿著前驅修改邊上的容量即可,這個時候我們並不需要使用d

fsdfs進行貪心,因為在進行若干次操作後一定會最大流

#include<bits/stdc++.h>
#define inf 0x7f
#define N 5005
#define M 50005
using namespace std;
int first[N],cnt=-1,n,m,s,t,d[N],pred[N],flow[N],in[N],pos[N];
struct Node{int v,next,c,w;}e[M<<1];
inline void add(int u,int v,int c,int w){
	e[++cnt].v=v;
	e[cnt].c=c;
	e[
cnt].w=w; e[cnt].next=first[u]; first[u]=cnt; } inline bool spfa(){ queue<int>q; q.push(s); memset(d,inf,sizeof(d)); memset(flow,inf,sizeof(flow)); memset(in,0,sizeof(in)); in[s]=1,pred[t]=-1,d[s]=0; while(!q.empty()){ int x=q.front(); q.pop(),in[x]=0; for(int i=first[x];i!=-1;i=e[
i].next){ int v=e[i].v; if(e[i].c>0&&d[v]>d[x]+e[i].w){ d[v]=d[x]+e[i].w; pred[v]=x; pos[v]=i; flow[v]=min(flow[x],e[i].c); if(!in[v]){ in[v]=1; q.push(v); } } } } return pred[t]!=-1; } inline void solve(){ int maxnf=0,maxnw=0; while(spfa()){ maxnf+=flow[t]; maxnw+=flow[t]*d[t]; int pot=t; while(pot!=s){ e[pos[pot]].c-=flow[t]; e[pos[pot]^1].c+=flow[t]; pot=pred[pot]; } } printf("%d %d",maxnf,maxnw); } int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1;i<=m;++i){ int u,v,c,w; scanf("%d%d%d%d",&u,&v,&c,&w); add(u,v,c,w); add(v,u,0,-w); } solve(); return 0; }