2018.06.27最小費用最大流模板
阿新 • • 發佈:2019-02-08
最小費用最大流是指整個容量網路在保證流量最大的情況下使花費的費用最小,所以說與求最大流的思想有所差異。
我們知道,求最大流的思想是每次找一條增廣路進行貪心直到貪不動為止,但是對於最小費用最大流這個問題來說,我們最後求得的一定是最大流,因此我們仍然每次貪心,只需保證費用最小即可。
於是我們使用而不是來找最短增廣路,我們在進行演算法的同時用一個的陣列來記錄對於當前節點,從路徑上離最近的點,即的前驅,最後從開始沿著前驅修改邊上的容量即可,這個時候我們並不需要使用進行貪心,因為在進行若干次操作後一定會最大流
#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;
}