最小费用最大流板子

整理一下自己的板子。详细的思路过程,也不太记得了,有空的话再回过头记录把。

//spfa法 
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5118,M=51108,inf=0x3f3f3f3f;
struct Side{
    int v,ne,w,val;
}S[2*M];
int s,t,sn,head[N],dis[N],vis[N],flow[N],lu[N];
void init(int n){
    sn=0;
    for(int i=0;i<=n;i++) head[i]=-1;
}
void add(int u,int v,int w,int val){
    S[sn].w=w;
    S[sn].v=v;
    S[sn].val=val;
    S[sn].ne=head[u];
    head[u]=sn++;
}
void addE(int u,int v,int w,int val){
    add(u,v,w,val);add(v,u,0,-val);
}
bool spfa(int n){
    queue<int> q;
    for(int i=0;i<=n;i++){ 
        dis[i]=inf;
        vis[i]=0;
        flow[i]=inf;
        lu[i]=-1;
    }
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=S[i].ne){
            int v=S[i].v;
            if(S[i].w>0&&dis[v]>dis[u]+S[i].val){
                lu[v]=i;
                dis[v]=dis[u]+S[i].val;
                flow[v]=min(flow[u],S[i].w);
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return dis[t]!=inf; 
}
void mfml(int n){
    int ans=0,ansc=0;
    while(spfa(n)){
        ans+=flow[t];
        ansc+=flow[t]*dis[t];
        for(int i=lu[t];i!=-1;i=lu[S[i^1].v]){
            S[i].w-=flow[t];
            S[i^1].w+=flow[t];
        }
    }
    printf("%d %d\n",ans,ansc);
}
int main(){
    int n,m,u,v,w,val;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    init(n);
    while(m--){
        scanf("%d%d%d%d",&u,&v,&w,&val);
        addE(u,v,w,val);
    }
    mfml(n);
    return 0;
}
//zwk费用流 
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5118,M=51108,inf=1e9+7;
struct Side{
    int v,ne,w,val;
}S[M<<1];
bool vis[N];
int sb,se,sn,ans,ansc,head[N],dis[N],cur[N];
void init(int n){
    sn=0;
    for(int i=0;i<=n;i++) head[i]=-1;
}
void add(int u,int v,int w,int val){
    S[sn].w=w;S[sn].val=val;
    S[sn].v=v;S[sn].ne=head[u];
    head[u]=sn++;
}
void addE(int u,int v,int w,int val){
    add(u,v,w,val);add(v,u,0,-val);
}
bool spfa(int n){
    for(int i=0;i<=n;i++){ 
        dis[i]=inf;
        vis[i]=false;
    }
    dis[se]=0;
    vis[se]=true;
    deque<int> q;
    q.push_back(se);
    while(!q.empty()){
        int u=q.front();
        q.pop_front();
        vis[u]=false;
        for(int i=head[u],v;~i;i=S[i].ne){
            v=S[i].v;
            if(S[i^1].w>0&&dis[v]>dis[u]-S[i].val){
                dis[v]=dis[u]-S[i].val;
                if(!vis[v]){
                    vis[v]=true;
                    if(!q.empty()&&dis[v]<dis[q.front()])
                        q.push_front(v);
                    else q.push_back(v);
                }
            }
        }
    }
    return dis[sb]!=inf; 
}
int dfs(int u,int minf){
    if(u==se){
        vis[se]=true;
        return minf;
    }
    vis[u]=true;
    int flow=0,temp,v;
    for(int &i=cur[u];~i;i=S[i].ne){
        v=S[i].v;
        if(!vis[v]&&S[i].w>0&&dis[v]==dis[u]-S[i].val){
            temp=dfs(v,min(S[i].w,minf-flow));
            if(temp){
                S[i].w-=temp;
                S[i^1].w+=temp;
                flow+=temp;
                ansc+=S[i].val*temp; 
            }
            if(flow==minf) break;
        }
    }
    return flow;
}
void mfml(int n){
    ans=ansc=0;
    while(spfa(n)){
        do{
            for(int i=0;i<=n;i++) vis[i]=false,cur[i]=head[i];
            ans+=dfs(sb,inf);
        }while(vis[se]);
    }
    printf("%d %d\n",ans,ansc);
}
int main(){
    int n,m,u,v,w,val;
    scanf("%d%d%d%d",&n,&m,&sb,&se);
    init(n);
    while(m--){
        scanf("%d%d%d%d",&u,&v,&w,&val);
        addE(u,v,w,val);
    }
    mfml(n);
    return 0;
}
//dijk费用流 
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5118,M=51108,inf=1e9+7;
struct Side{
    int v,ne,w,val;
    Side(){}
    Side(int v,int val):v(v),val(val){}
    bool operator<(const Side &s1)const{
        return val>s1.val;
    }
}S[M<<1];
bool vis[N];
int n,sb,se,sn,ansc,head[N],dis[N],flow[N],lu[N],h[N];
void init(int n){
    sn=0;
    for(int i=0;i<=n;i++) head[i]=-1;
}
void add(int u,int v,int w,int val){
    S[sn].w=w;S[sn].val=val;
    S[sn].v=v;S[sn].ne=head[u];
    head[u]=sn++;
}
void addE(int u,int v,int w,int val){
    add(u,v,w,val);add(v,u,0,-val); 
}
bool dijk(){
    priority_queue<Side> q;
    for(int i=0;i<=n;i++){
        lu[i]=-1;    
        dis[i]=flow[i]=inf;
    }
    dis[sb]=0;
    q.push(Side(sb,dis[sb]));
    while(!q.empty()){
        int u=q.top().v,w=q.top().val;q.pop();
        if(dis[u]<w) continue;
        for(int i=head[u];~i;i=S[i].ne){
            int v=S[i].v;
            if(S[i].w>0&&dis[v]>dis[u]+S[i].val+h[u]-h[v]){
                lu[v]=i;
                dis[v]=dis[u]+S[i].val+h[u]-h[v];
                flow[v]=min(flow[u],S[i].w);
                q.push(Side(v,dis[v]));
            }
        }
    }
    return dis[se]!=inf; 
}
int mfml(){
    int ans=0,ansc=0;
    for(int i=0;i<=n;i++) h[i]=0;
    while(dijk()){
        ans+=flow[se];
        ansc+=flow[se]*(dis[se]+h[se]-h[sb]);
        for(int i=lu[se];~i;i=lu[S[i^1].v]){
            S[i].w-=flow[se];
            S[i^1].w+=flow[se];
        }
        for(int i=0;i<=n;i++) h[i]+=dis[i];
    }
    printf("%d %d\n",ans,ansc); 
    return 0;
}
int main(){
    int m,u,v,w,val;
    scanf("%d%d%d%d",&n,&m,&sb,&se);
    init(n);
    while(m--){
        scanf("%d%d%d%d",&u,&v,&w,&val);
        addE(u,v,w,val);
    }
    mfml();
    return 0;
}

平常题spfa便可以过,毒瘤的时候,可以使用势函数优化的dijkstra版本,zwk费用流在某些数据(稠密图)下是最快的。

posted @ 2020-07-12 21:59  新之守护者  阅读(151)  评论(0编辑  收藏  举报