网络流&费用流模板
网络流dinic
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
bool bfs() { int head=0,tail=1; for(int i=0;i<=T;i++)h[i]=-1; q[0]=0;h[0]=0; while(head!=tail) { int now=q[head];head++; for(int i=last[now];i;i=e[i].next) if(e[i].v&&h[e[i].to]==-1) { h[e[i].to]=h[now]+1; q[tail++]=e[i].to; } } return h[T]!=-1; } int dfs(int x,int f) { if(x==T)return f; int w,used=0; for(int i=cur[x];i;i=e[i].next) if(h[e[i].to]==h[x]+1) { w=f-used; w=dfs(e[i].to,min(w,e[i].v)); e[i].v-=w;e[i^1].v+=w; if(e[i].v)cur[x]=i; used+=w;if(used==f)return f; } if(!used)h[x]=-1; return used; } void dinic() { while(bfs()) { for(int i=0;i<=T;i++) cur[i]=last[i]; ans+=dfs(0,inf); } } |
最小费用最大流spfa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
bool spfa() { for(int i=0;i<=T;i++)dis[i]=inf; int head=0,tail=1; dis[0]=0;q[0]=0;inq[0]=1; while(head!=tail) { int now=q[head++];if(head==1601)head=0; for(int i=last[now];i;i=e[i].next) if(e[i].v&&e[i].c+dis[now]<dis[e[i].to]) { dis[e[i].to]=e[i].c+dis[now]; from[e[i].to]=i; if(!inq[e[i].to]) { inq[e[i].to]=1; if(dis[e[i].to]<dis[q[head]]) { head--;if(head==-1)head=1600; q[head]=e[i].to; } else { q[tail++]=e[i].to; if(tail==1601)tail=0; } } } inq[now]=0; } if(dis[T]==inf)return 0; return 1; } void mcf() { int x=inf; for(int i=from[T];i;i=from[e[i].from]) x=min(e[i].v,x); for(int i=from[T];i;i=from[e[i].from]) { ans+=x*e[i].c; e[i].v-=x;e[i^1].v+=x; } } |
zkw费用流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
bool spfa() { memset(mark,0,sizeof(mark)); for(int i=0;i<=T;i++)d[i]=-1; int head=0,tail=1; q[0]=T;mark[T]=1;d[T]=0; while(head!=tail) { int now=q[head];head++;if(head==605)head=0; for(int i=last[now];i;i=e[i].next) if(e[i^1].v&&d[now]+e[i^1].c>d[e[i].to]) { d[e[i].to]=d[now]+e[i^1].c; if(!mark[e[i].to]) { mark[e[i].to]=1; q[tail++]=e[i].to; if(tail==605)tail=0; } } mark[now]=0; } return d[0]!=-1; } int dfs(int x,int f) { mark[x]=1; if(x==T)return f; int w,used=0; for(int i=last[x];i;i=e[i].next) if(d[e[i].to]==d[x]-e[i].c&&e[i].v&&!mark[e[i].to]) { w=f-used; w=dfs(e[i].to,min(w,e[i].v)); ans+=w*e[i].c; e[i].v-=w;e[i^1].v+=w; used+=w;if(used==f)return f; } return used; } void zkw() { while(spfa()) { mark[T]=1; while(mark[T]) { memset(mark,0,sizeof(mark)); dfs(0,inf); } } } |
不太理解为什么要反向跑spfa,我正向跑得也没有问题。。。。。
hzwer牛,能不能在ZKW模板里加点注释啊,还有其他用到的数组的含义,,,想盗一下模板又怕错,,
还有,学长,您的zkw模板里,dfs在过程中没有返回值 。。。
一般情况我们都只关心费用。。。
黄学长,请问最小费用最大流的两个算法的都各有什么取舍(在不同情况如何选择?)
都用zkw就好
似乎spfa的方法在稀疏图里更高效?(= =)
不是据说在 费用不小,流量不大,增广路比较长 的情况下zkw法比较慢吗?学长有没有遇到专业卡zkw的。。而且似乎刚刚看见一个Primal-Daul算法,请问学长能指点一下吗?
我觉得这不是研究的重点,你不好从题目中知道数据可能卡哪个算法吧
我只是觉得zkw不容易被卡
o,谢谢学长
orz黄学长,请问zkw是谁啊= =
THU张昆玮
1601是啥?
哦队列数组大小。。