费用流

· · 个人记录

SSP(Successive Shortest Path,连续最短路)算法

const ll inf=4557430888798830399ll;
ll dis[maxp];
bool in[maxp];
il bool spfa(){
    memset(dis+1,63,sizeof(ll)*tot);
    static int q[maxp<<6],hd,tl;
    dis[S]=0,q[hd=tl=1]=S,in[S]=1;
    static int now; static ll res;
    while(hd<=tl){
        now=q[hd++],in[now]=0;
        for(int i=ehd[now];i;i=e[i].nxt)
            if(e[i].c){
                res=dis[now]+e[i].l;
                if(dis[e[i].to]>res){
                    dis[e[i].to]=res;
                    if(!in[e[i].to]) q[++tl]=e[i].to,in[e[i].to]=1;
                }
            }
    }
    return dis[T]<inf;
}

il ll dfs(int now,ll fl){
    if(now==T) return fl;
    ll rest=fl,used; in[now]=1;
    for(int i=ehd[now];i;i=e[i].nxt)
        if(e[i].c && !in[e[i].to] && dis[e[i].to]==dis[now]+e[i].l){
            used=dfs(e[i].to,mymin(rest,e[i].c));
            e[i].c-=used,e[i^1].c+=used;
            rest-=used; if(!rest) break;
        }
    return fl-rest;
}

il pair<ll,ll> dinic(){
    static pair<ll,ll> ret;
    static ll res; ret=m_p(0ll,0ll);
    while(spfa()){
        while((res=dfs(S,inf))){
            memset(in+1,0,sizeof(bool)*tot);
            ret.fir+=res;
            ret.sec+=dis[T]*res;
        }
        memset(in+1,0,sizeof(bool)*tot);
    }
    return ret;
}
struct edge{
    int to,nxt; ll c,l;
    edge(){}
    edge(int _to,int _nxt,ll _c,ll _l){to=_to,nxt=_nxt,c=_c,l=_l;}
}e[maxm<<1];
int etot=1,ehd[maxp];
il void addedge(int s,int t,ll c,ll l){
    e[++etot]=edge(t,ehd[s],c,l),ehd[s]=etot;
    e[++etot]=edge(s,ehd[t],0,-l),ehd[t]=etot;
    return;
}

其他费用流算法

例题

P1251 餐巾计划问题

P2604 [ZJOI2010] 网络扩容

P4016 负载平衡问题

P4015 运输问题

P4014 分配问题

P4013 数字梯形问题

P4012 深海机器人问题

P3358 最长 k 可重区间集问题

P3357 最长 k 可重线段集问题

P2770 航空路线问题

P3356 火星探险问题

P4009 汽车加油行驶问题