zkw费用流 java_[模板] 网络流相关/最大流ISAP/费用流zkw

最大流/ISAP

话说ISAP是真快...(大多数情况)吊打dinic,而且还好写...

大概思路就是: 在dinic的基础上, 动态修改层数, 如果终点层数 $>$ 点数, break.

暂时并不知道isap有没有可能被卡. 应该不会

const int ninf=(int)1e9+500,psz=(int)450,esz=(int)1e5+50;

//network flow

struct te{int t,pr,fl;}edge[esz*2];

int hd[psz],pe=1,np,ss,tt; //np: number of points

void adde(int f,int t,int fl){edge[++pe]=(te){t,hd[f],fl};hd[f]=pe;}

void addsg(int f,int t,int fl){adde(f,t,fl);adde(t,f,0);} //add an unidirectional edge

void adddb(int f,int t,int fl){adde(f,t,fl);adde(t,f,fl);} //add a bi-directional edge

int d[psz],gap[psz],cur[psz];

void init(){ //bfs

rep(i,1,np)cur[i]=hd[i],gap[i]=0,d[i]=0;

static int que[psz],qh,qt;

qh=1,qt=0;

que[++qt]=tt,d[tt]=1,gap[1]=1;

while(qh<=qt){

int u=que[qh++];

for(int i=hd[u],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t){

if(d[v])continue;

d[v]=d[u]+1,++gap[d[v]];

que[++qt]=v;

}

}

}

int dfs(int p,int mi){

if(mi==0||p==tt)return mi;

int fl=0,tmp;

for(int &i=cur[p],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t){

if(d[v]+1!=d[p])continue;

tmp=dfs(v,min(edge[i].fl,mi));

fl+=tmp,mi-=tmp,edge[i].fl-=tmp,edge[i^1].fl+=tmp;

if(mi==0)return fl; //这个时候不需要修改d[p], 已经没有流量可以增广; 如果修改会wa,并不知道为什么,欢迎神仙指出

}

if(gap[d[p]]==1)d[ss]=np+1;

--gap[d[p]],++d[p],++gap[d[p]];

cur[p]=hd[p];

return fl;

}

int maxfl(){

int res=0;

init();

while(d[ss]<=np)res+=dfs(ss,ninf);

return res;

}

费用流/ZKW

跑的慢

const int psz=1e4+50,esz=1e5+50,ninf=1e9;

int n,m,s,t;

struct te{int t,c,v,pr;}edge[esz*2];

int hd[psz],pe=1,ss,tt,np;

void adde(int f,int t,int c,int v){edge[++pe]=(te){t,c,v,hd[f]};hd[f]=pe;}

void addsg(int f,int t,int c,int v){adde(f,t,c,v);adde(t,f,0,-v);}

int que[psz],qh=1,qt=0;

int mind[psz],cur[psz],vi[psz];

bool init(){

memcpy(cur,hd,(np+2)*4);

qh=1,qt=0;

rep(i,1,np)mind[i]=ninf,vi[i]=0;

que[++qt]=ss,mind[ss]=0,vi[ss]=1;

while(qh<=qt){

int u=que[qh%np];++qh,vi[u]=0;

for(int i=hd[u],v;i;i=edge[i].pr){

v=edge[i].t;

if(edge[i].c==0||mind[v]<=edge[i].v+mind[u])continue;

mind[v]=edge[i].v+mind[u];

if(vi[v]==0)++qt,que[qt%np]=v,vi[v]=1;

}

}

return mind[tt]

}

int dfs(int p,int mi){

if(p==tt||mi==0)return mi;

vi[p]=1;

int fl=0,tmp;

for(int &i=cur[p],v;i;i=edge[i].pr){

v=edge[i].t;

if(mind[v]!=mind[p]+edge[i].v||edge[i].c==0||vi[v])continue;

tmp=dfs(v,min(mi,edge[i].c));

fl+=tmp,mi-=tmp,edge[i].c-=tmp,edge[i^1].c+=tmp;

if(mi==0)break;//important

}

vi[p]=0;return fl;

}

int ansc=0,ansf=0;

void mcmf(){

while(init()){

int tmp=dfs(ss,ninf);

ansf+=tmp,ansc+=tmp*mind[tt];

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值