[gotoac]网络流SAP(邻接表&邻接矩阵) beta2

#define getmin(x,y) (x= (x<0 || (y)<x)? (y):x)
struct sap{//动态邻接表
	typedef int type;     //流量的类型
	struct edge{
		int from,to;
		type flow;   //该条边的剩余流量
		edge(int u=0,int v=0,type f=0){from=u,to=v,flow=f;}
	};
	int n,m;              //顶点数,边数(包括反向弧)
	int dis[M],cur[M];    //从起点到i的距离,当前所在的弧
	int gap[M],pre[M];    //距离标号计数,可增广路上的上一条弧的序号
	vector<edge>edg;      //边表
	vector<int>g[M];      //g[i][j]表示点i连接的第j条边的序号
	void init(int _n){    //初始化
		n=_n,edg.clear();
		for(int i=0;i<n;i++) g[i].clear();
	}
	void insert(int u,int v,type c){
		edg.push_back(edge(u,v,c)),edg.push_back(edge(v,u,0));
		m=edg.size();
		g[u].push_back(m-2),g[v].push_back(m-1);
	}
	type maxFlow(int s,int t){
		type res=0,a;
		clr(dis,0,n),clr(gap,0,n),clr(cur,0,n);
		gap[0]=n;
		for(int u=s;dis[s]<n;){
			if(u==t){//增广
				for(a=-1;u!=s;u=edg[pre[u]].from)
					getmin(a,edg[pre[u]].flow);
				for(u=t;u!=s;u=edg[pre[u]].from)
					edg[pre[u]].flow-=a,edg[pre[u]^1].flow+=a;
				res+=a;
			}
			bool ok=0;
			for(int i=cur[u];i<g[u].size();i++){//前推
				edge& e=edg[g[u][i]];
				if(dis[u]==dis[e.to]+1 && e.flow>0){
					pre[e.to]=g[u][i],cur[u]=i,u=e.to;
					ok=1;break;
				}
			}
			if(!ok){//回退
				int mindis=n-1;
				for(int i=0;i<g[u].size();i++){
					edge& e=edg[g[u][i]];
					if(e.flow>0 && mindis>dis[e.to])
						mindis=dis[e.to],cur[u]=i;
				}
				if(--gap[dis[u]]==0) break;
				gap[dis[u]=mindis+1]++;
				if(u!=s) u=edg[pre[u]].from;
			}
		}
		return res;
	}
};


struct sap{//静态邻接表
	typedef int type;
	struct edge{
		int v,next;
		type flow;
	}edg[999999];     //边表
	int head[M];      //邻接表
	int n,m;          //顶点数,边数
	int cur[M],dis[M];//当前弧,距离标号
	int pre[M],gap[M];//上一点,间隙优化
	void init(int _n){n=_n,m=0,clr(head,-1,n);}
	void insert(int u,int v,type f,type c=0){
		edg[m].flow=f,edg[m].v=v;
		edg[m].next=head[u],head[u]=m++;
		edg[m].flow=0,edg[m].v=u;
		edg[m].next=head[v],head[v]=m++;
	}
	type maxFlow(int s,int t){
		type res=0,a;
		int i;
		for(i=0;i<n;i++) cur[i]=head[i];
		clr(gap,0,n),clr(dis,0,n);
		gap[0]=n,pre[s]=s;
		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;
			for(i=cur[u];i!=-1;i=edg[i].next){
				edge& e=edg[i];
				if(dis[u]==dis[e.v]+1 && e.flow>0){
					pre[e.v]=u,cur[u]=i,u=e.v,ok=1;
					break;
				}
			}
			if(!ok){
				int mindis=n-1;
				for(i=head[u];i!=-1;i=edg[i].next){
					edge& e=edg[i];
					if(mindis>dis[e.v] && e.flow>0)
						mindis=dis[e.v],cur[u]=i;
				}
				if(--gap[dis[u]]==0) break;
				gap[dis[u]=mindis+1]++;
				u=pre[u];
			}
		}
		return res;
	}
};

 


struct sap{//邻接矩阵
	typedef int type;     //流量的类型
	int n;                //顶点数
	type flow[M][M];      //该条边的剩余流量
	int dis[M],cur[M];    //从起点到i的距离,当前所在的弧
	int gap[M],pre[M];    //距离标号计数,可增广路上的上一个点
	void init(int _n){    //初始化
		n=_n;
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
				flow[i][j]=0;
	}
	void insert(int u,int v,double f){flow[u][v]=f;}
	type maxFlow(int s,int t){
		clr(dis,0,n),clr(gap,0,n),clr(cur,0,n);
		gap[0]=n,pre[s]=s;
		type a,res=0;
		for(int u=s;dis[s]<n;){
			if(u==t){
				for(a=-1;u!=s;u=pre[u])
					getmin(a,flow[pre[u]][u]);
				for(u=t;u!=s;u=pre[u])
					flow[pre[u]][u]-=a,flow[u][pre[u]]+=a;
				res+=a;
			}
			bool ok=0;
			for(int v=cur[u];v<n;v++){
				if(dis[u]==dis[v]+1 && flow[u][v]>0){
					pre[v]=u,cur[u]=v,u=v;
					ok=1;break;
				}
			}
			if(!ok){
				int mindis=n-1;
				for(int v=0;v<n;v++)
					if(flow[u][v]>0 && mindis>dis[v])
						mindis=dis[v],cur[u]=v;
				if(--gap[dis[u]]==0) break;
				gap[dis[u]=mindis+1]++,u=pre[u];
			}
		}
		return res;
	}
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值