【洛谷】3381 【模板】最小費用最大流
阿新 • • 發佈:2019-02-07
划水啊,就是最小費用最大流的模板,只是標記一下自己會了這種演算法。
正解就是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; }