最小費用最大流(spfa增廣)——模板整理
阿新 • • 發佈:2019-01-10
這個演算法好像沒名字。。就是每次spfa增廣。
時間複雜度O(n*m^2*3)?
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=5005,maxe=100005;
int n,m,nxt[maxe],S,T,fir[maxn],tot=1,f[maxn],dis[maxn],path[maxn],ans1,ans2;
struct Edge { int from,to,cap,flow,cost; } Es[maxe];
queue <int> que;
bool vis[maxn];
void add(int x,int y,int w,int c){
Es[++tot]=(Edge){x,y,w,0,c};
nxt[tot]=fir[x]; fir[x]=tot;
Es[++tot]=(Edge){y,x,0,0,-c};
nxt[tot]=fir[y]; fir[y]=tot;
}
bool Find_SPFA(int s,int t,int &MaxFlow,int &MinCost){
memset(f,0,sizeof(f)); f[s]=1e+9 ;
memset(dis,63,sizeof(dis)); dis[s]=0;
memset(vis,0,sizeof(vis));
while(!que.empty()) que.pop();
que.push(s);
while(!que.empty()){
int x=que.front();
que.pop(); vis[x]=false;
for(int j=fir[x];j;j=nxt[j]){
if(Es[j].cap>Es[j].flow&&dis[x]+Es[j].cost<dis[Es[j].to]){
dis[Es[j].to]=dis[x]+Es[j].cost;
path[Es[j].to]=j;
f[Es[j].to]=min(f[x],Es[j].cap-Es[j].flow);
if (!vis[Es[j].to]) vis[Es[j].to]=true, que.push(Es[j].to);
}
}
}
if(!f[t]) return false;
MaxFlow+=f[t]; MinCost+=f[t]*dis[t];
for(int i=t;i!=s;i=Es[path[i]].from){
Es[path[i]].flow+=f[t];
Es[path[i]^1].flow-=f[t];
}
return true;
}
int main(){
scanf("%d%d%d%d",&n,&m,&S,&T);
for(int i=1;i<=m;i++){
int x,y,z,c; scanf("%d%d%d%d",&x,&y,&z,&c);
add(x,y,z,c);
}
ans1=ans2=0;
while(Find_SPFA(S,T,ans1,ans2));
printf("%d %d\n",ans1,ans2);
return 0;
}