网络流-最大流

最大流

dinic

  • 思路:先bfs找出每个点的深度,然后按照深度进行dfs
bool bfs()
{
	memset(dis,-1,sizeof(dis));
	memset(vst,0,sizeof(vst));
	queue <int> q;
	q.push(S);dis[S]=0;vst[S]=1;
	while(!q.empty())
	{
		int a=q.front(),x;q.pop();
		if(a==T)return 1;
		for(int i=h[a];i;i=g[i].next)
		{
			x=g[i].to;
			if(g[i].v>0&&vst[x]==0)
			{
				vst[x]=1;dis[x]=dis[a]+1;q.push(x);
			}
		}
	}
	return 0;
}
long long dfs(int a,long long maxx)
{
	long long res=0,dlt;
	int x;
	if(a==T||maxx==0)return maxx;
	for(int i=h[a];i;i=g[i].next)
	{
		x=g[i].to;
		if(g[i].v<=0||dis[x]!=dis[a]+1)continue;
		dlt=dfs(x,min(maxx,g[i].v));
		if(dlt==0)dis[x]=0;
		g[i].v-=dlt;g[i^1].v+=dlt;
		res+=dlt;maxx-=dlt;
		if(maxx==0)return res;
	}
	return res;
}
long long dinic()
{
	long long ans=0;
	while(bfs())
	{
		ans+=dfs(S,inf);
	}
	return ans;
}

sap

  • 思路:利用$ d[ ] \(数组记录每个点的当前深度,从深度高的点到深度小1的点dfs, \) gap[ ] $ 记录每个深度的点的数量,当增加当前点的深度后原深度的点的数量为0时,出现断层,无法继续dfs,标记$ d[T]=ed $然后退出循环
long long dfs(int a,long long maxx)
{
	if(a==T||maxx==0)return maxx;
	int x,i;
	long long dlt,res=0;
	for(i=h[a];i;i=g[i].next)
	{
		x=g[i].to;
		if(d[x]!=d[a]-1||g[i].v<=0)continue;
		dlt=dfs(x,min(maxx,g[i].v));
		g[i].v-=dlt;g[i^1].v+=dlt;
		res+=dlt;maxx-=dlt;
		if(maxx==0||d[T]==ed)return res;
	}
	if(--gap[d[a]]==0)d[T]=ed;
	d[a]++;gap[d[a]]++;
	return res;
}
long long sap()
{
	long long ans=0;gap[0]=n;
	while(d[T]!=ed)
	{
		ans+=dfs(S,inf);
	}
	return ans;
}
posted @ 2019-03-01 16:36  www233  阅读(187)  评论(0编辑  收藏  举报