【洛谷】3381 【模板】最小费用最大流

来源:互联网 发布:linux echo 编辑:程序博客网 时间:2024/06/05 21:03

题目传送门

划水啊,就是最小费用最大流的模板,只是标记一下自己会了这种算法。

正解就是SPFA+EK,在SPFA扩展的过程中加入EK的判断——这条边的流量是否还有剩余。

然后在所有节点都扩展完毕后进行EK的流量修改,最后统计答案。

附上AC代码:

#include <cstdio>#include <vector>#include <queue>#include <cstring>using namespace std;struct note{int from,to,w,v,nt;}side[100010];queue <int> que;int n,m,s,t,x,y,w,v,h[5010],dis[5010],f[5010],pre[5010],flow,cost,num;bool b[5010];void add(int x,int y,int w,int v){side[num]=(note){x,y,w,v,h[x]};h[x]=num++;}bool spfa(){for (int i=1; i<=n; ++i) dis[i]=1e9,b[i]=0;b[s]=1,dis[s]=0,f[s]=2e9,que.push(s);while (!que.empty()){int p=que.front();que.pop(),b[p]=0;for (int i=h[p]; ~i; i=side[i].nt)if (side[i].w&&dis[side[i].to]>dis[p]+side[i].v){dis[side[i].to]=dis[p]+side[i].v;pre[side[i].to]=i;f[side[i].to]=min(f[p],side[i].w);if (!b[side[i].to]){b[side[i].to]=1;que.push(side[i].to);}}}if (dis[t]==1e9) return 0;flow+=f[t];cost+=f[t]*dis[t];for (int i=t; i!=s; i=side[pre[i]].from){side[pre[i]].w-=f[t];side[pre[i]^1].w+=f[t];}return 1;}int main(void){scanf("%d%d%d%d",&n,&m,&s,&t);memset(h,-1,sizeof h);for (int i=1; i<=m; ++i){scanf("%d%d%d%d",&x,&y,&w,&v);add(x,y,w,v),add(y,x,0,-v);}while (spfa());printf("%d %d",flow,cost);return 0;}

0 0
原创粉丝点击