费用流
费用流问题指的是在网络流边权新增“代价”这一属性后,在得到最大流量的前提下最小化代价之和的问题。
我们依然使用基于增广路的算法,只不过每次使用Bellman_Ford来寻找最短路。
如果要求代价最小可以在代价变为正时停止增广。
代码:
struct Edge{
int u,v;LL cap,flow,cost;int next;
} E[maxn*2];
int n,m,x,y,S,T,Esize,pre[maxn],last[maxn];
LL val,c,d[maxn],a[maxn];
bool inq[maxn];
void addedge(int x,int y,LL v,LL c)
{
E[++Esize]=(Edge){x,y,v,0,c,last[x]},last[x]=Esize;
E[++Esize]=(Edge){y,x,0,0,-c,last[y]},last[y]=Esize;
}
bool Bellman_Ford(LL &flow,LL &cost)
{
memset(inq,0,sizeof(inq)),inq[S]=1; //注意初始化细节
rep(i,1,n) d[i]=INF;
d[S]=0,a[S]=INF,pre[S]=0;
queue<int> Q;Q.push(S);
while (!Q.empty())
{
x=Q.front();Q.pop();
for (int i=last[x];i;i=E[i].next)
if ((E[i].cap>E[i].flow)&&(d[E[i].v]>(d[x]+E[i].cost)))
{
d[E[i].v]=d[x]+E[i].cost;
pre[E[i].v]=i,a[E[i].v]=min(a[x],E[i].cap-E[i].cost);
if (!inq[E[i].v]) Q.push(E[i].v),inq[E[i].v]=1;
}
}
if (d[T]==INF) return false;
flow+=a[T],cost+=a[T]*d[T],x=T; //代价为d[T],流量为a[T]
while (x)
{
E[pre[x]].flow+=a[T],E[pre[x]^1].flow-=a[T];
x=E[pre[x]].u;
}
return true;
}
LL MCMF()
{
LL ans=0,flow=0;
while (Bellman_Ford(flow,ans)); //存在增广路则一直增广
return ans;
}

浙公网安备 33010602011771号