最小費用最大流模板
阿新 • • 發佈:2021-11-09
注意,spfa可能被卡,圖中存在負權
#include<bits/stdc++.h> using namespace std; #define int long long const int _ = 2e5+10; const int N = 1010,inf=0x3f3f3f3f; void in(int &x){ x=0;int y = 1; char c=getchar(); while(!isdigit(c)){if(c=='-')y=-1;c=getchar();} while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();} x*=y; } void o(int x){ printf("%lld",x); } int n,m,k; int a[_]; //前向星村邊,注意始邊從2開始,而不再是1。 struct Minicostflow{ // 起始,終點, int S,T,n; //邊,注意要存u struct EDG{int u,v,nxt,f,cost;}e[_];int cnt = 1; int head[_]; // 反邊花費為-cos void add(int u,int v,int f,int cos){ e[++cnt]={u,v,head[u],f,cos};head[u]=cnt; swap(u,v); e[++cnt]={u,v,head[u],0,-cos};head[u]=cnt; } //spfa 建立分層圖 int dis[_],in_queue[_],from[_]; bool spfa(){ for(int i=1;i<=n;i++)dis[i]=inf,in_queue[i]=0; queue<int>q;q.push(S);dis[S]=0;in_queue[S]=1; while(!q.empty()){ int u = q.front(); q.pop(); if(u==T)continue; for(int i=head[u];i;i=e[i].nxt){ EDG P = e[i]; if(P.f&&dis[P.v]>dis[u]+P.cost){ dis[P.v]=dis[u]+P.cost; from[P.v]=i; if(!in_queue[P.v]){ in_queue[P.v]=1; q.push(P.v); } } } in_queue[u]=0; } return dis[T]<inf; } // 最大流,最小費用 int maxflow,mincost; void mincostflow(){ maxflow = mincost = 0; while(spfa()){ int tmp = inf; for(int i=T;i!=S;i=e[from[i]].u)tmp = min(tmp,e[from[i]].f); maxflow+=tmp;mincost+=tmp*dis[T]; for(int i=T;i!=S;i=e[from[i]].u)e[from[i]].f-=tmp,e[from[i]^1].f+=tmp; } } }Minicostflow; signed main(){ in(n);in(m);in(Minicostflow.S);in(Minicostflow.T);Minicostflow.n=n; for(int u,v,f,c,i=1;i<=m;i++){ in(u);in(v);in(f);in(c); Minicostflow.add(u,v,f,c); } Minicostflow.mincostflow(); o(Minicostflow.maxflow);putchar(' '); o(Minicostflow.mincost);putchar('\n'); // o(MAXF.cal());putchar('\n'); return 0; }