您的位置:首页 > 其它

最小费用最大流<模板大法好QAQ>

2016-05-27 11:00 169 查看
先贴一个神犇送我的模板QAQ

bool bfs() // 求最短路,并且查看是否存在可增广路
{
Rep_0(i,N)dis[i] = inf; //初始化费用
int h,t;
dis[q[h = t = 1] = S] = 0,inq[S] = 1,flw[S] = inf;
while(h <= t)
{
int x = q[h ++];
RepG(i,x)
if(fl && dis[v] > dis[x] + cst) // 有流 && 可松弛
{
pre[v] = i ^ 1; //记录最短路的反向边路径
dis[v] = dis[x] + cst; //松弛
flw[v] = min(flw[x],fl); //flw[v]表示从S -> v的沿此条路径可获得的流量
if(!inq[v])inq[q[++ t] = v] = 1;
}
inq[x] = 0;
}
return dis[T] != inf; //是否存在增广路
}
int CostFlow()
{
int s = 0;int i ;
while(bfs())
{
for(int x = T;x != S;x = v)i = pre[x],fl += flw[T],vfl -= flw[T]; //走反向边,并且清掉路过的流量
s += flw[T] * dis[T];
//因为下次增广会覆盖掉flw数组,所以flw数组不用清零
}
return s;
}


已经注释。应该算是挺好懂的,比dinic不知道好懂到哪里去了。

接下来介绍几道题<从hzwer的blog上扒下来的>

bzoj1221:[HNOI]软件开发

Description

某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。

题解:

要注意到每天可以洗很多毛巾,但是每天产生的脏毛巾的数目是一定的,我们对于每天的脏毛巾和每天的需求进行考虑。

首先,每天都会产生nd[i]的脏毛巾,并且每天要么凭空多出新毛巾,要么拿以前的脏毛巾消毒后进行供应。

凭空:从S到某个点连上流量为ndi,费用为f的边。

拿以前的脏毛巾:从脏毛巾到当前时间 +消毒时间的地方连一个费用为消毒的话费,流量为当天的需求的边。

总建图的话:

首先是个二分图,左边为脏毛巾,右边为需要的干净毛巾。

Rep(i,n)
{
save(S,i + n,nd[i],f);
save(S,i,nd[i]);
if(i != n)save(i,i + 1,inf);
save(i + n,T,nd[i]);
if(i + a < n)save(i,i + a + 1 + n,nd[i + a + 1],fa);
if(i + b < n)save(i,i + b + 1 + n,nd[i + b + 1],fb);
}


这道题关键在于需要把脏毛巾和需求的毛巾分开考虑。

其它题先放着……看了半天图论恶心死了

~~不太喜欢网络流系列~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: