[ZJOI2010] 网络扩容

题意:

给定一张有向图,每条边都有一个容量c和一个扩容费用w。这里扩容费用是指将容量扩大1所需的费用。

求: 在不扩容的情况下,1到n的最大流;将1到n的最大流增加k所需的最小扩容费用。

$nleq 1000,mleq 5000$。

题解:

先跑一边最大流,然后对每条边$(u,v,c,0)$再建一条$(u,v,inf,w)$的边。

源点限流为k,在残量网络上再跑一遍最小费用最大流即可。

复杂度$O(能过)$。

代码:

#include<bits/stdc++.h>
#define maxn 1005
#define maxm 100005
#define inf 0x7fffffff
#define ll long long
#define rint register int
#define debug(x) cerr<<#x<<": "<<x<<endl
#define fgx cerr<<"--------------"<<endl
#define dgx cerr<<"=============="<<endl

using namespace std;
int n,m,k,hd[maxn],to[maxm],fl[maxm],nxt[maxm],cnt;
int dis[maxn],inq[maxn],cst[maxm],vis[maxn],cost;
struct edge{int u,v,c,w;}E[maxm];

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

inline void addedge(int u,int v,int w,int c){
    to[++cnt]=v,fl[cnt]=w,cst[cnt]=c;
    nxt[cnt]=hd[u],hd[u]=cnt;
}
inline bool spfa(int ed){
    queue<int> q;
    memset(dis,127,sizeof(dis));
    memset(inq,0,sizeof(inq));
    dis[1]=0,inq[1]=1,q.push(1);
    while(!q.empty()){
        int u=q.front();
        q.pop(),inq[u]=0;
        for(int i=hd[u];i;i=nxt[i]){
            int v=to[i],w=fl[i],c=cst[i];
            if(w>0 && dis[v]>dis[u]+c){
                dis[v]=dis[u]+c;
                if(!inq[v]) q.push(v),inq[v]=1;
            }
        }
    }
    return dis[ed]<=2e9;
}
inline int dfs(int u,int flow,int ed){
    if(u==ed) return flow;
    vis[u]=1; int sum=0;
    for(int i=hd[u];i;i=nxt[i]){
        int v=to[i],w=fl[i],c=cst[i];
        if(!vis[v] && w>0 && dis[v]==dis[u]+c){
            int f=dfs(v,min(flow,w),ed);
            sum+=f,cost+=f*c;
            flow-=f,fl[i]-=f,fl[i^1]+=f;
            if(!flow) break;
        }
    }
    if(!sum) dis[u]=inf;
    return sum;
}

inline int Dinic(){
    memset(hd,0,sizeof(hd)),cnt=1;
    for(int i=1;i<=m;i++){
        addedge(E[i].u,E[i].v,E[i].c,0);
        addedge(E[i].v,E[i].u,0,0);
    }
    int ans=0; 
    while(spfa(n)){
        memset(vis,0,sizeof(vis));
        ans+=dfs(1,inf,n);
    }
    return ans;
}

inline int MCMF(int res){
    for(int i=1;i<=m;i++){
        addedge(E[i].u,E[i].v,inf,E[i].w);
        addedge(E[i].v,E[i].u,0,-E[i].w);
    }
    addedge(n,n+1,k,0);
    int ans=0; 
    while(spfa(n+1)){
        memset(vis,0,sizeof(vis));
        ans+=dfs(1,inf,n+1);
    }
    return cost;
}

int main(){
    n=read(),m=read(),k=read();
    for(int i=1;i<=m;i++)
        E[i].u=read(),E[i].v=read(),E[i].c=read(),E[i].w=read();
    int res=Dinic();
    printf("%d %d
",res,MCMF(res));
    return 0;
}
网络扩容
原文地址:https://www.cnblogs.com/YSFAC/p/13211857.html