1. 程式人生 > 其它 >(最小費用最大流)洛谷P3381【模板】最小費用最大流

(最小費用最大流)洛谷P3381【模板】最小費用最大流

技術標籤:圖論

洛谷P3381【模板】最小費用最大流

思路:

在一個網路中,每條邊有一個流量 f f f和費用 w w w,表示限制的流量和每單位流量需要花費的費用。最小費用最大流也叫費用流,就是求在最大化 ∑ f \sum f f的情況下,最小化 ∑ f × w \sum f\times w f×w
那麼我們將求增廣路的BFS替換成SPFA就可以從求任意增廣路到求一條從 s s s t t t的最短路的增廣路。

程式碼:

#include<bits/stdc++.h>
#define pii pair<int,int>
#define
ll long long
#define cl(x,y) memset(x,y,sizeof(x)) #define loop(x,y,z) for(x=y;x<=z;x++) #define reve(x,y,z) for(x=y;x>=z;x--) #define ct cerr<<"Time elapsed:"<<1.0*clock()/CLOCKS_PER_SEC<<"s.\n"; #define mp make_pair #define pb push_back #define fi first #define
se second
#define all(x) x.begin(),x.end() #define lson x<<1,l,mid #define rson x<<1|1,mid+1,r #define INF 1e18 const int N=1e4+10; const int M=1e6+10; const int mod=1e9+7; const int inf=0x3f3f3f3f; const double eps=1e-8; const double pi=acos(-1); using namespace std; struct edge { int u,
v,f,w; }e[M]; int head[N],len=1,dis[N],vis[N]; int maxflow,mincost; int pre[N],path[N]; void add(int u,int v,int f,int w) { e[++len]={head[u],v,f,w}; head[u]=len; } void inc(int u,int v,int f,int w) { add(u,v,f,w); add(v,u,0,-w); } int spfa(int s,int t) { cl(dis,inf); cl(vis,0); cl(pre,-1); dis[s]=0; vis[s]=1; queue<int>q; q.push(s); while(!q.empty()) { int u=q.front(),i; q.pop(); vis[u]=0; for(i=head[u];i;i=e[i].u) { int v=e[i].v,w=e[i].w; if(e[i].f && dis[v]>dis[u]+w) { dis[v]=dis[u]+w; pre[v]=u; path[v]=i; if(!vis[v]) { q.push(v); vis[v]=1; } } } } return pre[t]!=-1; } void ek(int s,int t) { while(spfa(s,t)) { int mi=inf,i; for(i=t;i!=s;i=pre[i]) mi=min(mi,e[path[i]].f); for(i=t;i!=s;i=pre[i]) { e[path[i]].f-=mi; e[path[i]^1].f+=mi; } maxflow+=mi; mincost+=dis[t]*mi; } } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n,m,s,t,i; cin>>n>>m>>s>>t; for(i=1;i<=m;i++) { int u,v,f,w; cin>>u>>v>>f>>w; inc(u,v,f,w); } ek(s,t); cout<<maxflow<<" "<<mincost<<endl; return 0; }