网络流费用流入门(洛谷P3381)

来源:互联网 发布:sat 知乎 编辑:程序博客网 时间:2024/05/16 15:28

算法用途

最小费用最大流问题是经济学和管理学中的一类典型问题。在一个网络中每段路径都有“容量”和“费用”两个限制的条件下,此类问题的研究试图寻找出:流量从A到B,如何选择路径、分配经过路径的流量,可以在流量最大的前提下,达到所用的费用最小的要求。

算法先决条件

建议在学费用流之前先学会 最大流 与 SPFA

算法实现

具体算法和EK差不多,只不过找增广路由BFS改为SPFA(因为多了距离这个限制条件)。对于已经会最大流的同学还是比较简单的。

模板

以洛谷P3381为例:

#include<cstdio>#include<cstring>#include<algorithm>#define MAXN 5000#define MAXM 50000using namespace std;struct edge{    int next,to,v,flow,dis;};struct father{    int x,e;};int n,m,k,s,t;int h[MAXN+5],dis[MAXN+5],que[2*MAXM+5],rem[MAXN+5];bool f[MAXN+5];edge ed[MAXM*2+5];father fa[MAXN+5];inline char readc(){    static char buf[100000],*l=buf,*r=buf;    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);    if (l==r) return EOF; return *l++;}inline int _read(){    int num=0; char ch=readc();    while (ch<'0'||ch>'9') ch=readc();    while (ch>='0'&&ch<='9') { num=num*10+ch-48; ch=readc(); }    return num;}void addedge(int x,int y,int w,int z){    ed[k].next=h[x]; ed[k].to=y; ed[k].v=w; ed[k].dis=z; h[x]=k++;    ed[k].next=h[y]; ed[k].to=x; ed[k].v=0; ed[k].dis=-z; h[y]=k++;}int spfa(){    memset(f,false,sizeof(f));    memset(dis,0x3f3f3f3f,sizeof(dis));    dis[s]=0; que[1]=s; rem[s]=0x7fffffff;    int r=0,w=1;    while (r<w){        int x=que[++r]; f[x]=false;        for (int i=h[x];~i;i=ed[i].next)            if (ed[i].v>ed[i].flow&&dis[ed[i].to]>dis[x]+ed[i].dis){                int v=ed[i].to;                dis[v]=dis[x]+ed[i].dis;                fa[v].x=x; fa[v].e=i;                rem[v]=min(rem[x],ed[i].v-ed[i].flow);                if (!f[v]) { f[v]=true; que[++w]=v; }            }    }    if (dis[t]==0x3f3f3f3f) return 0;    return rem[t];}void change(int sum){    int now=t;    while (now!=s){        int e=fa[now].e;        ed[e].flow+=sum; ed[e^1].flow-=sum; now=fa[now].x;    }}void mcmf(){    int ans=0,cst=0;    while (1){        int sum=spfa();        if (!sum) { printf("%d %d\n",ans,cst); return; }        ans+=sum; cst+=dis[t]*sum; change(sum);    }}int main(){    n=_read(); m=_read(); s=_read(); t=_read();    memset(h,-1,sizeof(h));    for (int i=1;i<=m;i++){        int u=_read(),v=_read(),c=_read(),d=_read();        addedge(u,v,c,d);    }    mcmf();    return 0;}
原创粉丝点击