[gotoac] sap(bfs+邻接表) beta1

struct sap{
	typedef int type;
	struct edge{
		int to,next;
		type flow;
	}edg[999999];//边表
	int n,m;//顶点数,边数
	int g[M],cur[M],pre[M];//邻接表,当前弧,上一个点
	int dis[M],gap[M];//层次数组,间隙优化
	int q[M],head,tail;//队列
	void init(int _n){n=_n,m=0,clr_all(g,-1);}//初始化
	void insert(int u,int v,type f,type c=0){//插边
		edg[m].to=v,edg[m].flow=f,edg[m].next=g[u],g[u]=m++;
		edg[m].to=u,edg[m].flow=0,edg[m].next=g[v],g[v]=m++;
	}
	bool bfs(int s,int t){//反向广搜,初始化层次数组
		clr(gap,0,n),clr(dis,-1,n);
		gap[dis[t]=0]++,dis[s]=-1;
		for(q[head=tail=0]=t;head<=tail;){
			int u=q[head++];
			for(int i=g[u];i!=-1;i=edg[i].next){
				edge& e=edg[i],ee=edg[i^1];
				if(dis[e.to]==-1 && ee.flow>0){
					gap[dis[e.to]=dis[u]+1]++;
					q[++tail]=e.to;
				}
			}
		}
		return dis[s]!=-1;
	}
	type maxFlow(int s,int t){//求最大流
		if(!bfs(s,t)) return 0;
		type res=0,a;
		int i;
		for(i=0;i<n;i++) cur[i]=g[i];
		pre[s]=s,cur[s]=g[s],cur[t]=g[t];
		for(int u=s;dis[s]<n;){
			if(u==t){//增广
				for(a=-1;u!=s;u=pre[u])
					getmin(a,edg[cur[pre[u]]].flow);
				for(u=t;u!=s;u=pre[u]){
					edg[cur[pre[u]]].flow-=a;
					edg[cur[pre[u]]^1].flow+=a;
				}
				res+=a;
			}
			bool ok=0;//当前增广路是否能前推的标志,0否,1是
			for(i=cur[u];i!=-1;i=edg[i].next){//前推
				edge& e=edg[i];
				if(dis[u]==dis[e.to]+1 && e.flow>0){
					cur[u]=i,pre[e.to]=u,u=e.to;
					ok=1;break;
				}
			}
			if(ok) continue;
			int mindis=n-1;
			for(i=g[u];i!=-1;i=edg[i].next){//当前增光路不能前推,回退
				edge& e=edg[i];
				if(mindis>dis[e.to] && e.flow>0)
					mindis=dis[e.to],cur[u]=i;
			}
			if(--gap[dis[u]]==0) break;//出现断层,当前流是最大流
			gap[dis[u]=mindis+1]++,u=pre[u];
		}
		return res;
	}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值