网络流

高质量博客

网络最大流

#include<bits/stdc++.h>
using namespace std;
#define N 1205
#define M 120005
#define int long long
const int inf=1e18;
int n,m,s,t,head,tail,dis[N],q[N*20],k,h[N],he[N],x,y,z;
struct AB{
    int a,b,c,n;
}d[M*2];
void cun(int x,int y,int z){d[++k]=(AB){x,y,z,h[x]},h[x]=k;}
void bfs(){
    memset(dis,-1,sizeof(dis));
    q[head=tail=1]=s,dis[s]=0;
    while(head<=tail){
        int x=q[head++];
        for(int i=h[x];i;i=d[i].n){
            int y=d[i].b;
            if(d[i].c&&dis[y]==-1){
                dis[y]=dis[x]+1;
                q[++tail]=y;
            }
        }
    }
}
int dfs(int x,int f){
    if(x==t) return f;
    int ff=f;
    for(int &i=h[x];i;i=d[i].n){//当前弧优化 
        int y=d[i].b;
        if(!d[i].c||dis[y]!=dis[x]+1) continue;
        int dick=dfs(y,min(d[i].c,ff));
        if(dick){
            d[i].c-=dick,d[i^1].c+=dick,ff-=dick;
            if(!ff) break;
        }
        else dis[y]=0;//炸点优化 
    }
    return f-ff;
}
int dinic(){
    int ans=0;
    while(1){
        memcpy(h,he,sizeof(he));
        bfs();
        if(dis[t]==-1) break;
        ans+=dfs(s,inf);
    }
    return ans;
}
signed main(){
    scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
    k++;
    for(int i=1;i<=m;i++){
        scanf("%lld%lld%lld",&x,&y,&z);
        cun(x,y,z),cun(y,x,0);
    } 
    memcpy(he,h,sizeof(h));
    printf("%lld",dinic());
    return 0;
}

最小费用最大流

dij

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 5005
#define M 50005
const int inf=1e18;
int n,m,s,t,k,h[N],hh[N],u[N],dis[N],he[N],vis[N],ans1,ans2,x,y,z,zz;
struct AB{
    int a,b,c,v,n;
}d[M*2];
void cun(int x,int y,int z,int zz){
    d[++k]=(AB){x,y,z,zz,h[x]},h[x]=k;
}
priority_queue<pair<int,int> ,vector<pair<int,int> >,greater<pair<int,int> > > q;
void dij(int x){
    memset(u,0,sizeof(u));
    memset(dis,9,sizeof(dis));
    dis[x]=0,q.push(make_pair(dis[x],x));
    while(!q.empty()){
        x=q.top().second,q.pop();
        if(u[x]) continue;
        u[x]=1;
        for(int i=h[x];i;i=d[i].n){
            int y=d[i].b;
            if(d[i].c&&dis[x]+d[i].v+hh[x]-hh[y]<dis[y]){
                dis[y]=dis[x]+d[i].v+hh[x]-hh[y];
                q.push(make_pair(dis[y],y));
            }
        }
    }
}
int dfs(int x,int f){
    if(x==t) return f;
    int ff=f;
    vis[x]=1;
    for(int &i=h[x];i;i=d[i].n){
        int y=d[i].b;
        if(!d[i].c||dis[y]!=dis[x]+d[i].v+hh[x]-hh[y]||vis[y]) continue;
        int dd=dfs(y,min(d[i].c,ff));
        if(dd){
            d[i].c-=dd,d[i^1].c+=dd,ff-=dd;
            if(!ff) break;
        }
    }
    if(f-ff) vis[x]=0;
    return f-ff;
}
void mcmf(){
    int flag=0;
    while(1){
        memcpy(h,he,sizeof(h));
        dij(s);
        if(dis[t]==dis[0]) break;
        memset(vis,0,sizeof(vis));
        int p=dfs(s,inf);
        if(!p) break;
        ans1+=p,ans2+=p*(dis[t]+hh[t]);
        for(int i=1;i<=n;i++) hh[i]+=dis[i];
    }
}
signed main(){
    scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
    k++;
    for(int i=1;i<=m;i++){
        scanf("%lld%lld%lld%lld",&x,&y,&z,&zz);
        cun(x,y,z,zz),cun(y,x,0,-zz);
    }
    memcpy(he,h,sizeof(h));
    mcmf();
    printf("%lld %lld",ans1,ans2);
    return 0;
}

spfa

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 5005
#define M 50005
int n,m,s,t,ans1,ans2,k;
const int inf=1e18;
int h[N],he[N],dis[N],u[N],vis[N],q[N*20];
struct AB{
    int a,b,c,d,n;
}d[M*2];
void cun(int x,int y,int z,int v){
    d[++k]=(AB){x,y,z,v,h[x]},h[x]=k;
}
void lian(int x,int y,int z,int v){
    cun(x,y,z,v),cun(y,x,0,-v);
}
void spfa(int x){
    int head,tail;
    memset(dis,127,sizeof(dis));
    memset(u,0,sizeof(u));
    q[head=tail=1]=x,dis[x]=0,u[x]=1;
    while(head<=tail){
        x=q[head++],u[x]=0;
        for(int i=h[x];i;i=d[i].n){
            int y=d[i].b;
            if(!d[i].c||dis[y]<=dis[x]+d[i].d) continue;
            dis[y]=dis[x]+d[i].d;
            if(!u[y]) q[++tail]=y,u[y]=1;
        }
    }
}
int dfs(int x,int f){
    if(x==t) return f;
    int ff=f;
    vis[x]=1;
    for(int &i=h[x];i;i=d[i].n){
        int y=d[i].b;
        if(!d[i].c||dis[x]+d[i].d!=dis[y]||vis[y]) continue;
        int fl=dfs(y,min(ff,d[i].c));
        if(fl){
            ff-=fl,d[i].c-=fl,d[i^1].c+=fl;
            if(!ff) break;
        }
    }
    if(f-ff) vis[x]=0;
    return f-ff;
}
void dinic(){
    while(1){
        memcpy(h,he,sizeof(he));
        spfa(s);
        if(dis[t]==dis[0]) break;
        memset(vis,0,sizeof(vis));
        int cnt=dfs(s,inf);
        if(!cnt) break;
//      printf("%lld\n",cnt);
        ans1+=cnt,ans2+=cnt*dis[t];
    }
}
signed main(){
    k++;
    scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
    for(int i=1,x,y,z,v;i<=m;i++){
        scanf("%lld%lld%lld%lld",&x,&y,&z,&v);
        lian(x,y,z,v);
    }
    memcpy(he,h,sizeof(h));
    dinic();
    printf("%lld %lld",ans1,ans2);
    return 0;
}

无源汇上下界可行流

#include<bits/stdc++.h>
using namespace std;
#define N 205
#define M 10205
int n,m,dis[N],h[N],he[N],q[N*20],ru[N],k,sum,ans,head,tail,s,t;
const int inf=1e9;
struct AB{
    int a,b,l,h,c,n;
}d[M*2+N*2];
void cun(int a,int b,int c,int dd){d[++k]=(AB){a,b,c,dd,dd-c,h[a]},h[a]=k;}
void bfs(int s){
    memset(dis,-1,sizeof(dis));
    int x,y;
    q[head=tail=1]=s,dis[s]=0;
    while(head<=tail){
        x=q[head++];
        for(int i=he[x];i;i=d[i].n){
            y=d[i].b;
            if(d[i].c&&dis[y]==-1){
                dis[y]=dis[x]+1;
                q[++tail]=y;
            }
        }
    }
}
int dfs(int x,int f){
    if(x==t) return f;
    int ff=f,y,dd;
    for(int &i=h[x];i;i=d[i].n){
        y=d[i].b;
        if(!d[i].c||dis[y]!=dis[x]+1) continue;
        dd=dfs(y,min(d[i].c,ff));
        if(dd){
            d[i].c-=dd,d[i^1].c+=dd,ff-=dd;
            if(!ff) break;
        }
        else dis[y]=0;
    }
    return f-ff;
}
void dinic(){
    while(1){
        bfs(s);
        if(dis[t]==-1) break ;
        memcpy(h,he,sizeof(he));
        ans+=dfs(s,inf);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    k=1,s=0,t=n+1;
    for(int i=1,a,b,c,d;i<=m;i++){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        cun(a,b,c,d),cun(b,a,0,0);
        ru[a]-=c,ru[b]+=c;
    }
    for(int i=1;i<=n;i++){
        if(ru[i]>0) cun(s,i,0,ru[i]),cun(i,s,0,0),sum+=ru[i];
        if(ru[i]<0) cun(i,t,0,-ru[i]),cun(t,i,0,0);
    }
    memcpy(he,h,sizeof(h));
    dinic();
    if(ans!=sum) printf("NO\n");
    else{
        printf("YES\n");
        for(int i=3;i<=m*2+1;i+=2) printf("%d\n",d[i].c+d[i^1].l);
    }
    return 0;
}

有源汇有上下界最大流

#include<bits/stdc++.h>
using namespace std;
#define N 205
#define M 10205
int n,m,dis[N],h[N],he[N],q[N*20],ru[N],k,sum,ans,head,tail,s,t,ss,tt,ans1;
const int inf=1e9;
struct AB{
    int a,b,l,h,c,n;
}d[M*2+N*2];
void cun(int a,int b,int c,int dd){d[++k]=(AB){a,b,c,dd,dd-c,h[a]},h[a]=k;}
void bfs(int s){
    memset(dis,-1,sizeof(dis));
    int x,y;
    q[head=tail=1]=s,dis[s]=0;
    while(head<=tail){
        x=q[head++];
        for(int i=he[x];i;i=d[i].n){
            y=d[i].b;
            if(d[i].c&&dis[y]==-1){
                dis[y]=dis[x]+1;
                q[++tail]=y;
            }
        }
    }
}
int dfs(int x,int f){
    if(x==t) return f;
    int ff=f,y,dd;
    for(int &i=h[x];i;i=d[i].n){
        y=d[i].b;
        if(!d[i].c||dis[y]!=dis[x]+1) continue;
        dd=dfs(y,min(d[i].c,ff));
        if(dd){
            d[i].c-=dd,d[i^1].c+=dd,ff-=dd;
            if(!ff) break;
        }
        else dis[y]=0;
    }
    return f-ff;
}
void dinic(){
    while(1){
        bfs(s);
        if(dis[t]==-1) break ;
        memcpy(h,he,sizeof(he));
        ans+=dfs(s,inf);
    }
}

int main(){
    scanf("%d%d%d%d",&n,&m,&ss,&tt);
    k=1,s=0,t=n+1;
    for(int i=1,a,b,c,d;i<=m;i++){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        cun(a,b,c,d),cun(b,a,0,0);
        ru[a]-=c,ru[b]+=c;
    }
    cun(tt,ss,0,inf),cun(ss,tt,0,0);
    for(int i=1;i<=n;i++){
        if(ru[i]>0) cun(s,i,0,ru[i]),cun(i,s,0,0),sum+=ru[i];
        if(ru[i]<0) cun(i,t,0,-ru[i]),cun(t,i,0,0);
    }
    memcpy(he,h,sizeof(h));
    dinic();
    if(ans!=sum) printf("please go home to sleep\n");
    else{
        ans=0,s=ss,t=tt;
        for(int i=h[t];i;i=d[i].n){
            if(d[i].b==s){
                ans1=d[i^1].c,d[i].c=d[i^1].c=0;
                break;
            }
        }
        dinic();
        printf("%d\n",ans+ans1);
    }
    return 0;
}

有源汇有上下界最小流

#include<bits/stdc++.h>
using namespace std;
#define N 500010
#define M 125010
int n,m,dis[N],h[N],he[N],q[N*20],ru[N],k,sum,ans,head,tail,s,t,ss,tt,ans1;
const int inf=1e9;
struct AB{
    int a,b,l,h,c,n;
}d[M*2+N*2];
void cun(int a,int b,int c,int dd){d[++k]=(AB){a,b,c,dd,dd-c,h[a]},h[a]=k;}
void bfs(int s){
    memset(dis,-1,sizeof(dis));
    int x,y;
    q[head=tail=1]=s,dis[s]=0;
    while(head<=tail){
        x=q[head++];
        for(int i=he[x];i;i=d[i].n){
            y=d[i].b;
            if(d[i].c&&dis[y]==-1){
                dis[y]=dis[x]+1;
                q[++tail]=y;
            }
        }
    }
}
int dfs(int x,int f){
    if(x==t) return f;
    int ff=f,y,dd;
    for(int &i=h[x];i;i=d[i].n){
        y=d[i].b;
        if(!d[i].c||dis[y]!=dis[x]+1) continue;
        dd=dfs(y,min(d[i].c,ff));
        if(dd){
            d[i].c-=dd,d[i^1].c+=dd,ff-=dd;
            if(!ff) break;
        }
        else dis[y]=0;
    }
    return f-ff;
}
void dinic(){
    while(1){
        bfs(s);
        if(dis[t]==-1) break ;
        memcpy(h,he,sizeof(he));
        ans+=dfs(s,inf);
    }
}

int main(){
    scanf("%d%d%d%d",&n,&m,&ss,&tt);
    k=1,s=0,t=n+1;
    for(int i=1,a,b,c,d;i<=m;i++){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        cun(a,b,c,d),cun(b,a,0,0);
        ru[a]-=c,ru[b]+=c;
    }
    cun(tt,ss,0,inf),cun(ss,tt,0,0);
    for(int i=1;i<=n;i++){
        if(ru[i]>0) cun(s,i,0,ru[i]),cun(i,s,0,0),sum+=ru[i];
        if(ru[i]<0) cun(i,t,0,-ru[i]),cun(t,i,0,0);
    }
    memcpy(he,h,sizeof(h));
    dinic();
    if(ans!=sum) printf("please go home to sleep\n");
    else{
        ans=0,s=ss,t=tt;
        for(int i=h[t];i;i=d[i].n){
            if(d[i].b==s){
                ans1=d[i^1].c,d[i].c=d[i^1].c=0;
                break;
            }
        }
        s=tt,t=ss;
        dinic();
        printf("%d\n",ans1-ans);
    }
    return 0;
}
posted @ 2022-08-12 19:12  hubingshan  阅读(15)  评论(0)    收藏  举报  来源