网络流dinic模板

bool makelevel()
{
	memset(level,-1,sizeof(level));
	q[1]=0;
	level[0]=0;
	head=1,tail=1;
	for(int head=1;head<=tail;head++)
	{
		for(int i=lin[q[head]];i;i=e[i].next)
		{
			if(level[e[i].y]<0&&e[i].v>0)
			{
				level[e[i].y]=level[q[head]]+1;
				q[++tail]=e[i].y;
			}
		}
	}
	return level[n+m+1]>=0;
}
int MAXflow(int aa,int flow)
{
	if(aa==n+m+1)return flow;
	int maxflow=0,d=0;
	for(int i=lin[aa];i&&maxflow<flow;i=e[i].next)
	{
		if(e[i].v&&level[e[i].y]==level[aa]+1)
		{
			if(d=MAXflow(e[i].y,min(flow-maxflow,e[i].v)))
			{
				e[i].v-=d;
				e[e[i].h].v+=d;
				maxflow+=d;
			}
		}
	}
	if(maxflow<=0) level[aa]=-1;
	return maxflow;
}
void dinic()
{
	int d;
	while(makelevel())
		while(d=MAXflow(0,99999999))
				ans+=d;
}

  费用流模板

bool spfa()
{
	memset(vis,0,sizeof(vis));
	memset(dis,12,sizeof(dis));
	dis[1]=0; vis[1]=true;
	q[0]=1; 
	int head=0,tail=0;
	while (head<=tail) //队列不为空
	{
		int tn=q[head++];
		for (int te=link[tn];te;te=edge[te].next)  //枚举边
		{
			int ty=edge[te].y;
			if (edge[te].flow &&(dis[tn]+edge[te].v<dis[ty]))  //首先的有流量再判断费用
			{
				if (!vis[ty])  //不在队列里。
				{
					q[++tail]=ty;
					vis[ty]=true;
				}
				dis[ty]=dis[tn]+edge[te].v;
				lastnode[ty]=tn; lastedge[ty]=te;   //增广路的记录,用于下面的增广。
			}
		}
		vis[tn]=false;
	}
	return(dis[t]!=oo); //如果到t的最短距离存在,表明存在一个费用最小的增广路。
}
void agu()  //按照增广路径进行流量增减
{
	int delta=oo;
	for (int now=t;now!=s;now=lastnode[now])
		if (edge[lastedge[now]].flow<delta )   //找出流量
			delta=edge[lastedge[now]].flow;
	for (int now=t;now!=s;now=lastnode[now])  //更新流量
	{
		int te=lastedge[now];
		edge[te].flow-=delta;
		int re=edge[te].reverse;
		edge[re].flow+=delta;
		ans+=delta*(-edge[te].v);
	}
}
void costflow()
{
	while (spfa())
		agu();
	cout<<ans<<endl;
}

  

posted @ 2018-03-26 16:38  mybing  阅读(224)  评论(0编辑  收藏  举报