BZOJ 1834: [ZJOI2010]network 网络扩容

第一问直接拍一个 dinic
第二问在第一问做完之后的残量网络上加上一些费用为 w[i] ,流量为 k 的边,新建一个源点,加一条费用为 0 ,流量为 k 的边连向原来的源点以限制流量。
主要是有些细节问题。
mdzz spfa 队列开小 WA 了一次。。

#include
#include
#include
#define g getchar()
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,n) for(int i=1;i<=n;++i)
#define fi(i,j,k) for(int i=j;i<=k;++i)
#define di(i,j,k) for(int i=j;i>=k;--i)
using namespace std;
inline ll read(){
    ll x=0,f=1;char ch=g;
    for(;ch<'0'||ch>'9';ch=g)if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=g)x=x*10+ch-'0';
    return x*f;
}
inline void out(ll x){
    int a[25],wei=0;
    if(x<0)putchar('-'),x=-x;
    for(;x;x/=10)a[++wei]=x%10;
    if(wei==0){puts("0");return;}
    for(int j=wei;j>=1;--j)putchar('0'+a[j]);
    putchar('\n');
}
struct re{int v,w,c,next;}ed[100005];struct re2{int x,y,w,c;}data[5005];
int pd[1005],dui[100005],head[1005],n,ans,ans2,dis[1005],from[1005],m,k,e=1;
inline void insert(int x,int y,int w,int c){ed[++e]=(re){y,w,c,head[x]};head[x]=e;}
void ins(int x,int y,int w){insert(x,y,w,0);insert(y,x,0,0);}
void ins(int x,int y,int w,int c){insert(x,y,w,c);insert(y,x,0,-c);}
bool jud[1005];
bool bfs(){
    memset(pd,-1,sizeof(pd));
    dui[1]=1;pd[1]=0;int tou=1,wei=1;
    for(;tou<=wei;++tou){
        int u=dui[tou];
        for(int i=head[u];i;i=ed[i].next){
            int v=ed[i].v;
            if(pd[v]==-1&&ed[i].w){pd[v]=pd[u]+1;dui[++wei]=v;}
        }
    }
    return pd[n]!=-1;
}
int dfs(int x,int fl){
    int used=0;
    if(x==n)return fl;
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v;
        if(pd[x]+1==pd[v]&&ed[i].w){
            int w=fl-used;
            w=dfs(v,min(w,ed[i].w));
            used+=w;ed[i].w-=w;ed[i^1].w+=w;
            if(used==fl)return fl;
        }
    }
    if(!used)pd[x]=-1;
    return used;
}
void dinic(){for(;bfs();)ans+=dfs(1,inf);}
bool spfa(){

    memset(pd,-1,sizeof(pd));
    memset(jud,0,sizeof(jud));
    memset(dis,inf,sizeof(dis));
    dui[1]=0;pd[0]=0;dis[0]=0;jud[0]=1;
    int tou=1,wei=1;
    for(;tou<=wei;jud[dui[tou]]=0,++tou){
        int u=dui[tou];
        for(int i=head[u];i;i=ed[i].next){
            int v=ed[i].v;
            if(ed[i].w&&dis[v]>dis[u]+ed[i].c){
                dis[v]=ed[i].c+dis[u];
                from[v]=i;
                if(!jud[v])dui[++wei]=v;
            }
        }
    }
    if(dis[n]==inf)return 0;
    int fr=from[n],fl=inf;
    for(;fr;fr=from[ed[fr^1].v])fl=min(fl,ed[fr].w);fr=from[n];
    for(;fr;fr=from[ed[fr^1].v])ans2+=ed[fr].c*fl,ed[fr].w-=fl,ed[fr^1].w+=fl;
    return 1;
}
void mcf(){for(;spfa(););}
int main(){
//  freopen("1.in","r",stdin);
    n=read();m=read();k=read();
    rep(i,m){
        int x=read(),y=read(),w=read(),c=read();
        data[i]=(re2){x,y,w,c};
        ins(x,y,w);
    }
    dinic();
    printf("%d ",ans);
//  rep(i,e){if(i%2)ed[i].w=0;}
//  rep(i,e){if(i%2)ed[i^1].w+=ed[i].w,ed[i].w=0;}
    ins(0,1,k,0);
    rep(i,m)ins(data[i].x,data[i].y,k,data[i].c);
    mcf();out(ans2);
    return 0;
}

你可能感兴趣的:(bzoj,费用流,网络流)