最小费用最大流(spfa增广)——模板整理

这个算法好像没名字。。就是每次spfa增广。
时间复杂度O(n*m^2*3)?

#include
#include
#include
#include
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].costif(!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;
}

你可能感兴趣的:(网络流,我的OI学习足迹)