• 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; 
    }    
    

      

  • 相关阅读:
    .NET 使用EF执行存储过程你知道几种?
    SQLserver 如何优雅的行转列
    SQLserver 如何获取近1月、近3个月、近6月数据
    三汇自动挂断问题:SIP兼容性,ACK检测,忽略ACK开启。
    几个flutter 开源项目测试
    Android versions for all users globally
    Using Flutter 2 on M1 MacOS Apple Silicon
    Educational Codeforces Round 111
    Wannafly挑战赛1
    摆烂记录
  • 原文地址:https://www.cnblogs.com/guangheli/p/10658906.html
Copyright © 2020-2023  润新知