BZOJ 1834: [ZJOI2010]network 网络扩容 最小费用流_最大流_残量网络

对于第一问,跑一遍最大流即可.

对于第二问,在残量网络上的两点间建立边 <u,v>,容量为无限大,费用为扩充费用.

跑一遍最小费用流即可.

Code:

#include <vector> 
#include <cstdio>
#include <queue> 
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin) 
#define inf 100000000 
#define maxn 100000 
#define ll long long 
using namespace std;
struct Edges{
    int u,v,c,w; 
}EDGE[maxn]; 
int n,m,k,s,t; 
struct Edge{
    int from,to,cap,cost; 
    Edge(int u,int v,int c,int f) : from(u),to(v),cap(c),cost(f){} 
}; 
vector<int>G[maxn]; 
vector<Edge>edges; 
void addedge(int u,int v,int c,int f){
    edges.push_back(Edge(u,v,c,f)); 
    edges.push_back(Edge(v,u,0,-f)); 
    int o = edges.size(); 
    G[u].push_back(o - 2); 
    G[v].push_back(o - 1); 
}
namespace Dinic{    
    int d[maxn],vis[maxn]; 
    queue<int>Q; 
    int BFS(){
        memset(vis,0,sizeof(vis)); 
        vis[s] = 1,d[s] = 0; Q.push(s); 
        while(!Q.empty()){
            int u = Q.front(); Q.pop(); 
            int sz = G[u].size();
            for(int i=0;i<sz;++i) {
                Edge r = edges[G[u][i]]; 
                if(!vis[r.to] && r.cap > 0) {
                    d[r.to] = d[u] + 1;
                    vis[r.to] = 1; 
                    Q.push(r.to); 
                }
            }
        }
        return vis[t]; 
    }
    int current[maxn]; 
    int DFS(int x,int cur){
        if(x==t) return cur; 
        int flow=0,f; 
        int sz = G[x].size(); 
        for(int i=current[x];i<sz;++i) {
            int u = G[x][i]; 
            Edge r = edges[u]; 
            if(d[r.to] == d[x] + 1 && r.cap > 0){
                f = DFS(r.to,min(cur,r.cap)); 
                if(f > 0) {
                    flow += f; 
                    cur -= f; 
                    edges[u].cap -= f;
                    edges[u^1].cap += f; 
                }
            }
            if(cur==0) break; 
        }
        return flow; 
    }
    int maxflow(){
        int flow=0;
        while(BFS()){
            memset(current,0,sizeof(current)); 
            flow += DFS(s,inf); 
        }
        return flow; 
    }
}; 
namespace MCMF{
    queue<int>Q; 
    int d[maxn],inq[maxn]; 
    int flow2[maxn],a[maxn];       
    long long ans; 
    int SPFA(){
        for(int i=0;i<maxn;++i) d[i] = flow2[i] = inf; 
        memset(inq,0,sizeof(inq)); 
        inq[s] = 1; d[s] = 0;      
        Q.push(s); 
        while(!Q.empty()){
            int u=Q.front();Q.pop(); inq[u] = 0; 
            int sz = G[u].size();
            for(int i=0;i<sz;++i) {       
                Edge r = edges[G[u][i]]; 
                if(r.cap > 0 && d[r.to] > d[u] + r.cost) {
                    d[r.to] = d[u] + r.cost;    
                    a[r.to] = G[u][i]; 
                    flow2[r.to] = min(flow2[u],r.cap); 
                    if(!inq[r.to]) {
                        inq[r.to] = 1;
                        Q.push(r.to); 
                    }
                } 
            }
        }
        if(flow2[t] == inf) return 0;       
        int f = flow2[t];  
        edges[a[t]].cap -= f, edges[a[t] ^ 1].cap += f; 
        int u = edges[a[t]].from; 
        while(u != s){
            edges[a[u]].cap -= f; 
            edges[a[u]^1].cap += f; 
            u = edges[a[u]].from; 
        }
        ans += (ll)(d[t] * f); 
        return 1; 
    }
    long long  getcost(){    
        while(SPFA()); 
        return ans; 
    }   
}; 
int main(){
    //setIO("input"); 
    scanf("%d%d%d",&n,&m,&k); 
    s = 1, t = n; 
    for(int i = 1;i <= m; ++i)  scanf("%d%d%d%d",&EDGE[i].u,&EDGE[i].v,&EDGE[i].c,&EDGE[i].w); 
    for(int i = 1;i <= m; ++i) 
        addedge(EDGE[i].u,EDGE[i].v,EDGE[i].c,0);     
    printf("%d ",Dinic::maxflow()); 
    for(int i = 1;i <= m; ++i) 
        addedge(EDGE[i].u,EDGE[i].v,inf,EDGE[i].w);     
    s = 0 , t = n + 1;        
    addedge(s,1,k,0);
    addedge(n,n+1,k,0); 
    printf("%lld",MCMF::getcost());         
    return 0; 
}    

  

posted @ 2019-04-05 15:50  EM-LGH  阅读(162)  评论(0编辑  收藏  举报