有源汇带上下界最小流

  LOj 模板
思路我就不多说了吧,和有源汇带上下界最大流一样,只不过这次是初流-残流网络最大流。关键这个模板题写的过程无限T一组,让我很绝望。在网上搜罗了很多代码,发现我有些地方可以优化。

  (1)跑dinic的时候可以使用当前弧优化

  (2)在dinic过程中,如果rest已经等于0了,直接返回。不要不管他,感觉没什么影响,其实有的数据会卡死的(千万在边权更新之后再返回)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=5e4+10;
const int M=6e5+10;
const int inf=1LL<<30;
int ans,n,m,s,t,S,T,tot=1,sout,flow,maxflow,lin[N],in[M],A[N],d[N],cur[N];
struct node{int y,v,n;}e[M];
inline int read(){
    char ch=getchar();int num=0,f=1;
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
    return num*f;
}
inline void add(int x,int y,int w){
    e[++tot].y=y;e[tot].n=lin[x];lin[x]=tot;e[tot].v=w;
    e[++tot].y=x;e[tot].n=lin[y];lin[y]=tot;e[tot].v=0;
}
inline bool bfs(int id){
    memset(d,0,sizeof(d));
    queue<int>q;
    if(id==1) q.push(S),d[S]=1;
    else q.push(t),d[t]=1;
    while(q.size()){
        int x=q.front();q.pop();
        for(int i=lin[x];i;i=e[i].n){
            int y=e[i].y;
            if(e[i].v&&!d[y]){
                d[y]=d[x]+1;
                q.push(y);
                if(id==1&&y==T) return 1;
                if(id==2&&y==s) return 1;
            }
        }
    }
    return 0;
}
inline int dinic(int x,int flow,int id){
    if(id==1&&x==T) return flow;
    if(id==2&&x==s) return flow;
    int rest=flow;
    for(int &i=cur[x];rest&&i;i=e[i].n){
        int y=e[i].y;
        if(e[i].v&&d[y]==d[x]+1){
            int k=dinic(y,min(rest,e[i].v),id);
            if(!k) d[y]=0;
            rest-=k;
            e[i].v-=k;
            e[i^1].v+=k;
            if(!rest) return flow-rest;
        }
    }
    return flow-rest;
}
int main(){
    //freopen("h.in","r",stdin);
    //freopen("h.out","w",stdout);
    n=read(),m=read(),s=read(),t=read();
    for(int i=1;i<=m;++i){
        int x=read(),y=read(),l=read(),r=read();
        add(x,y,r-l);
        A[y]+=l,A[x]-=l;
        //if(x==s) ans+=l;
    }
    S=0,T=n+1;
    for(int i=1;i<=n;++i){
        if(A[i]>0) add(S,i,A[i]),sout+=A[i];
        else if(A[i]<0) add(i,T,-A[i]);
    }
    add(t,s,inf);
    while(bfs(1)){
        for(int i=0;i<=T;++i) cur[i]=lin[i];
        while(flow=dinic(S,inf,1)) maxflow+=flow;
    }
    if(maxflow!=sout){
        printf("please go home to sleep\n");
    }else{
        ans+=e[tot].v;
        maxflow=0;
        e[tot].v=e[tot^1].v=0;
        while(bfs(2)){
            for(int i=0;i<=T;++i) cur[i]=lin[i];
            while(flow=dinic(t,inf,2)) maxflow+=flow;
        }
        ans-=maxflow;
        printf("%d\n",ans);
        //prllf("%d\n",maxflow);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/kgxw0430/p/10265040.html