设为首页 收藏本站
查看: 954|回复: 0

[经验分享] 最大流 Dinic + Sap 模板

[复制链接]

尚未签到

发表于 2015-9-19 13:13:32 | 显示全部楼层 |阅读模式
  不说别的,直接上模板。
  
  Dinic+当前弧优化:



struct Edge{
int x,y,c,ne;
}e[M*2];
int be[N],all;
int d[N],q[N];
int stack[N],top;//栈存的是边
int cur[N];//当前弧优化

void add(int x, int y, int z)//需保证相反边第一个为偶数
{
e[all].x=x; e[all].y=y; e[all].c=z;
e[all].ne=be[x];
be[x]=all++;
e[all].x=y; e[all].y=x; e[all].c=0;
e[all].ne=be[y];
be[y]=all++;
}

bool BFS(int s, int t)//化为层次图 使得边数从m降低为n 复杂度随之下降
{
memset(d,-1,sizeof(d));
int head=0,tail=0;
q[++tail]=s;
d=0;
while(head!=tail)
{
int u=q[++head];
for(int i=be; i!=-1; i=e.ne)
if(e.c>0 && d[e.y]==-1){
d[e.y]=d+1;
q[++tail]=e.y;
if(tail==N-1) tail=0;
if(e.y==t) return 1;
}
}
return 0;
}
int Dinic(int s, int t)//防止爆栈 用stack模拟递归
{
int ans=0;
while(BFS(s,t))
{
memcpy(cur,be,sizeof(be));
int u=s;
top=0;//dfs开始 清空栈
while(1)
{
if(u==t)
{
int minc=1000000000,mini;
for(int i=0; i<top; i++)
if(minc>e[stack].c)
{
minc=e[stack].c;
mini=i;//以便之后回到这继续增广
                    }
for(int i=0; i<top; i++)
{
e[stack].c-=minc;
e[stack^1].c+=minc;//第一个二进制取反 即取相反边
                }
ans+=minc;
top=mini;
u=e[stack[mini]].x;
}
for(int i=cur; i!=-1; cur=i=e[cur].ne)
if(e.c>0 && d[e.y]==d[e.x]+1) break;
if(cur!=-1)
{
stack[top++]=cur;
u=e[cur].y;
}else
{
if(top==0) break;   //循环结束标志
d=-1;//当前节点不在增广路中 删除
u=e[stack[--top]].x;//回溯
            }
}
}
return ans;
}
  ISAP+GAP+当前弧优化:



struct Edge{
int x,y,c,ne;
}e[M*2];
int x,y,z,n,m,s,t;
int be[N],all;
int d[N],q[N];
int stack[N];//模拟递归
int gap[N],cur[N];//gap优化+当前弧优化
void add(int x, int y, int z)//保证第一个为偶数
{
e[all].x=x; e[all].y=y; e[all].c=z;
e[all].ne=be[x];
be[x]=all++;
e[all].x=y; e[all].y=x; e[all].c=0;
e[all].ne=be[y];
be[y]=all++;
}
void BFS(int s, int t)
{
memset(d,-1,sizeof(d));
memset(gap,0,sizeof(gap));
gap[0]=1;
int head=0,tail=0;
q[++tail]=t;
d[t]=0;
while(head!=tail)
{
int u=q[++head];
for(int i=be; i!=-1; i=e.ne)
if(d[e.y]==-1)
{
d[e.y]=d+1;
q[++tail]=e.y;
gap[d[e.y]]++;
}
}
}
int sap(int s, int t, int n)
{
int ans=0;
BFS(s,t);
memcpy(cur,be,sizeof(be));
int top=0;
int u=s;
while(d<n)
{
if(u==t)
{
int minc=1000000000,mini;
for(int i=0; i<top; i++)
if(minc>e[stack].c)
{
minc=e[stack].c;
mini=i;
}
for(int i=0; i<top; i++)
{
e[stack].c-=minc;
e[stack^1].c+=minc;
}
ans+=minc;
top=mini;
u=e[stack[mini]].x;
continue;
}
for(int i=cur; i!=-1; cur=i=e.ne)//当前弧优化
if(e.c>0 && d[e.y]+1==d) break;
if(cur!=-1)
{
stack[top++]=cur;
u=e[cur].y;
}else
{
int mind=n;
for(int i=be; i!=-1; i=e.ne)//更新距离标号
if(e.c>0 && mind>d[e.y])
{
mind=d[e.y];
cur=i;
}
gap[d]--;
if(!gap[d]) return ans;//gap表示当前距离的点有多少个 一旦==0 说明断层直接退出循环
d=mind+1;
gap[d]++;
if(u!=s) u=e[stack[--top]].x;
}
}
return ans;
}
void init()
{
all=0;
memset(be,-1,sizeof(be));
}
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-115853-1-1.html 上篇帖子: 实现在一个SAP系统中调用其它SAP系统的功能 下篇帖子: SAP ABAP Performance Tuning Tricks Introduction/介绍下ABAP的性能调整窍门
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表