网络流库

最大流库

使用 Dinic 实现,支持输出最小割

#include<iostream>
#ifndef DINIC_HPP

#include<vector>
#include<queue>
#include<algorithm>
#include<limits>

namespace _dinic{

namespace __detail{

using size_t=long long;

template<size_t Node_cnt,typename Flow_type=long long>
class dinic{
    struct ed_t{
        bool isori;
        size_t v,rid;
        Flow_type flo;
    };
    std::vector<ed_t> *ed;
    size_t _S,_T;
    Flow_type _ans;
    size_t *lev,*cur;
    size_t _ncnt;
    bool _bfs(){
        std::fill(lev,lev+_ncnt+1,-1);
        lev[_S]=1;
        std::queue<size_t> que;
        que.push(_S);
        while(!que.empty()){
            size_t u=que.front();
            que.pop();
            for(auto &e:ed[u]){
                if(e.flo==0) continue;
                if(lev[e.v]==-1){
                    lev[e.v]=lev[u]+1;
                    que.push(e.v);
                }
            }
        }
        return lev[_T]!=-1;
    }
    Flow_type _dfs(size_t it,Flow_type tflo){
        if(it==_T) return tflo;
        Flow_type rest=tflo;
        for(size_t &i=cur[it];i<(size_t)ed[it].size();++i){
            auto &e=ed[it][i];
            if(e.flo==0||lev[e.v]!=lev[it]+1) continue;
            Flow_type rec=_dfs(e.v,std::min(rest,e.flo));
            if(rec==0){
                lev[e.v]=-1;
            }else{
                e.flo-=rec;
                rest-=rec;
                ed[e.v][e.rid].flo+=rec;
                if(rest==0) break;
            }
        }
        return tflo-rest;
    }
public:
    dinic(int S,int T):
        ed(new std::vector<ed_t>[Node_cnt+1]),
        _S(S),_T(T),_ans(0),
        lev(new size_t[Node_cnt+1]),
        cur(new size_t[Node_cnt+1]),
        _ncnt(0){}
    dinic(const dinic &o)=delete;
    dinic &operator=(const dinic &o)=delete;
    dinic(dinic &&o)=delete;
    ~dinic(){
        delete[] ed;
        delete[] lev;
        delete[] cur;
    }
    void add_edge(size_t u,size_t v,Flow_type flo){
        ed_t fo{true,v,(size_t)ed[v].size(),flo},ba{false,u,(size_t)ed[u].size(),0};
        ed[u].push_back(fo);
        ed[v].push_back(ba);
        if(_ncnt<u) _ncnt=u;
        if(_ncnt<v) _ncnt=v;
        return ;
    }
    Flow_type max_flow(){
        while(_bfs()){
            std::fill(cur,cur+_ncnt+1,0);
            _ans+=_dfs(_S,std::numeric_limits<Flow_type>::max());
        }
        return _ans;
    }
    std::vector<std::pair<size_t,size_t> > get_min_cut(){
        std::vector<std::pair<size_t,size_t> > ret;
        for(size_t i=1;i<=_ncnt;++i){
            for(auto &e:ed[i]){
                if(e.isori&&e.flo==0){
                    ret.push_back(std::make_pair(i,e.v));
                }
            }
        }
        return ret;
    }
};

} //namespace __detail

using __detail::dinic;

}//namespace _dinic

#endif // DINIC_HPP
#include<iostream>
using namespace std;
constexpr int MAXN=200,MAXM=500;
int N=0,M=0,S=0,T=0;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin>>N>>M>>S>>T;
    _dinic::dinic<MAXN> G(S,T);
    for(int i=1;i<=M;i++){
        int u,v,flo;
        cin>>u>>v>>flo;
        G.add_edge(u,v,flo);
    }
    cout<<G.max_flow()<<endl;
    return 0;
}

费用流库

使用 SPFA + EK 实现。

#include<iostream>
#include<vector>
#include<limits>
#include<deque>
template<int NSIZ,typename Flow_t,typename Cost_t,typename Comp=std::less<Cost_t> >
class min_cost_max_flow_t{
    static Cost_t min(const Cost_t &a,const Cost_t &b){return Comp()(b,a)?b:a;}
    static bool tomin(Cost_t &a,const Cost_t &b){if(Comp()(b,a)){a=b; return 1;} return 0;}
    struct ed_t{
        int v,r; Flow_t f; Cost_t c;
        bool operator>(const ed_t &o)const{
            return Comp()(o.c,c);
        }
    };
    int ncnt;
    std::vector<std::vector<ed_t> > ed;
    std::vector<char> vis;
    std::vector<Cost_t> dis;
    std::vector<Flow_t> Flow;
    std::vector<int> rev;
    std::deque<int> dque;
    std::vector<char> in;
    void upd(){
        if(dque.size()>=2){
            if(Comp()(dis[dque.back()],dis[dque.front()]))
                std::swap(dque.front(),dque.back());
        }
        return ;
    }
    void spfa(int S){
        std::fill(vis.begin(),vis.begin()+ncnt+1,0);
        std::fill(Flow.begin(),Flow.begin()+ncnt+1,0);
        std::fill(rev.begin(),rev.begin()+ncnt+1,-1);
        dis[S]=0; Flow[S]=std::numeric_limits<Flow_t>::max();
        vis[S]=1; dque.push_back(S); in[S]=1;
        while(!dque.empty()){
            int it=dque.front(); dque.pop_front(); in[it]=0;
            upd();
            for(auto e:ed[it])if(e.f>0){
                if((!vis[e.v])||Comp()(dis[it]+e.c,dis[e.v])){
                    dis[e.v]=dis[it]+e.c;
                    vis[e.v]=1;
                    Flow[e.v]=std::min(Flow[it],e.f);
                    rev[e.v]=e.r;
                    if(!in[e.v]){
                        dque.push_back(e.v); in[e.v]=1;
                        upd();
                    }
                }
            }
        }
        return ;
    }
public:
    min_cost_max_flow_t():ncnt(0),ed(NSIZ+1),vis(NSIZ+1),
        dis(NSIZ+1),Flow(NSIZ+1),rev(NSIZ+1),in(NSIZ+1){}
    void connect(int u,int v,Flow_t f,Cost_t c){
        if(ncnt<u) ncnt=u;
        if(ncnt<v) ncnt=v;
        int usiz=ed[u].size(),vsiz=ed[v].size();
        ed[u].push_back({v,vsiz,f,c});
        ed[v].push_back({u,usiz,0,-c});
        return ;
    }
    std::pair<Flow_t,Cost_t> maxflow(int S,int T){
        Flow_t flow=0; Cost_t cost=0;
        while(1){
            spfa(S);
            if(rev[T]==-1) break;
            Flow_t f=Flow[T];
            flow+=f;
            for(int it=T;rev[it]!=-1;){
                auto &re=ed[it][rev[it]];
                auto &e=ed[re.v][re.r];
                cost+=e.c*f;
                e.f-=f;
                re.f+=f;
                it=re.v;
            }
        }
        return {flow,cost};
    }
};
using ll=long long;
constexpr int MAXN=5e3,MAXM=5e4;
int main(){
    min_cost_max_flow_t<MAXN,ll,ll> G;
    using std::cin; using std::cout;
    int n,m,s,t; cin>>n>>m>>s>>t;
    for(int i=1;i<=m;i++){
        int u,v,w,c; cin>>u>>v>>w>>c;
        G.connect(u,v,w,c);
    }
    auto pi=G.maxflow(s,t);
    cout<<pi.first<<' '<<pi.second<<'\n';
    return 0;
}

费用流库(二)

使用网络单纯形算法实现,期望复杂度 \(O(nm)\)\(n,m\) 分别为点数和边数),擅长稠密图

#include<bits/stdc++.h>
/*
 * Watch out!
 * The sum of cost times the sum of flow must less than the limit of type!
*/
template<int Node_cnt,int Edge_cnt,typename cost_t,typename flow_t>
class min_cost_max_flow_t{
    template<typename Tp>
    static bool tomin(Tp &x,const Tp &y){if(y<x){x=y; return 1;} return 0;}
    static constexpr int NSI=Node_cnt,ESI=(Edge_cnt+1)*2;
    struct ed_t{int nxt,to; flow_t f; cost_t c;};
    int n,m,S,T;
    std::vector<char> vis;
    std::vector<int> hd,Fa,Fe,dep,buf;
    std::vector<cost_t> dis;
    std::vector<ed_t> E;
    void build(int it,int fa,int fe){
        vis[it]=1;
        Fa[it]=fa; Fe[it]=fe;
        for(int j=hd[it];j!=0;j=E[j].nxt)if(!vis[E[j].to]){
            build(E[j].to,it,j^1);
        } 
        return ;
    }
    void upd(int it){
        if(it==0||vis[it]) return ;
        vis[it]=1;
        upd(Fa[it]);
        dep[it]=dep[Fa[it]]+1;
        dis[it]=dis[Fa[it]]+E[Fe[it]].c;
        return ;
    }
    int getlca(int x,int y){
        while(x!=y) (dep[y]>=dep[x])?y=Fa[y]:x=Fa[x];
        return x;
    }
    void pushflow(int j){
        int l=NSI,r=NSI;
        buf[l]=j;
        int u=E[j^1].to,v=E[j].to;
        int lca=getlca(u,v);
        for(int i=u;i!=lca;i=Fa[i]) buf[--l]=Fe[i]^1;
        for(int i=v;i!=lca;i=Fa[i]) buf[++r]=Fe[i];
        int del=NSI; cost_t f=E[j].f;
        for(int i=l;i<=r;i++) if(tomin(f,E[buf[i]].f)) del=i;
        for(int i=l;i<=r;i++){int s=buf[i]; E[s].f-=f; E[s^1].f+=f;}
        if(del==NSI) return ;  
        if(del<NSI){
            for(int i=del+1;i<=NSI;i++){
                int s=buf[i];
                Fa[E[s^1].to]=E[s].to;
                Fe[E[s^1].to]=s;
            }
        }else{
            for(int i=NSI;i<=del-1;i++){
                int s=buf[i];
                Fa[E[s].to]=E[s^1].to;
                Fe[E[s].to]=s^1;
            }
        }
        std::fill(vis.begin()+1,vis.begin()+n+1,0);
        return ;
    }
public:
    min_cost_max_flow_t():n(0),m(1),S(0),T(0),
        vis(NSI+5,0),hd(NSI+5,0),Fa(NSI+5,0),Fe(NSI+5,0),dep(NSI+5,0),buf(NSI*2+5,0),
        dis(NSI+5,0),E(ESI+5){}
    void connect(int u,int v,flow_t f,cost_t c){
        E[++m]={hd[u],v,f,c}; hd[u]=m;
        E[++m]={hd[v],u,0,-c}; hd[v]=m;
        return ;
    }
    std::pair<flow_t,cost_t> solve(int _n,int _s,int _t){
        n=_n; S=_s, T=_t;
        flow_t sflow=0; cost_t scost=0;
        for(int j=2;j<=m;j++){
            auto &e=E[j];
            sflow+=e.f; if(e.c>0) scost+=e.c;
        }
        connect(S,T,sflow,scost+1); 
        std::swap(E[m-1].f,E[m].f);
        flow_t flow=0; cost_t cost=0;
        build(S,0,0); std::fill(vis.begin()+1,vis.begin()+n+1,0);
        while(1){
            bool ok=0;
            for(int j=2;j<=m;j++){
                auto &e=E[j];
                if(e.f>0){
                    int u=E[j^1].to,v=e.to;
                    upd(u); upd(v);
                    if(e.c-dis[u]+dis[v]<0){
                        pushflow(j);
                        ok=1;
                    }
                }
            }
            if(!ok) break;
        }
        for(int j=3;j<m;j+=2){
            auto &e=E[j];
            if(e.to==S) flow+=e.f;
            if(E[j^1].to==S) flow-=e.f;
            cost+=-e.c*e.f;
        }
        return {flow,cost};
    }
};

using std::cerr; using std::setw; using std::endl; using std::cin; using std::cout;
template<typename Tp>
bool tomax(Tp &x,const Tp &y){if(x<y){x=y; return 1;} return 0;}
template<typename Tp>
bool tomin(Tp &x,const Tp &y){if(y<x){x=y; return 1;} return 0;}
using ll=long long; using ui=unsigned; using lf=double; using ull=unsigned long long;
constexpr int MAXN=200,MAXM=1e4;
int main(){
    std::ios::sync_with_stdio(0); std::cin.tie(0); std::cout.tie(0);
    int N,M,S,T;
    min_cost_max_flow_t<MAXN,MAXM,int,int> G;
    cin>>N>>M>>S>>T;
    for(int m=1;m<=M;m++){
        int u,v,f,c; cin>>u>>v>>f>>c;
        G.connect(u,v,f,c);
    }
    auto pi=G.solve(N,S,T);
    cout<<pi.first<<' '<<pi.second<<'\n';
    return 0;
}
posted @ 2025-01-23 09:51  zhiyin123123  阅读(18)  评论(0)    收藏  举报
目录侧边栏

qwq