• bzoj1834: [ZJOI2010]network 网络扩容


    这道题分为俩步,第一是求最大流,第二是在第一问的残量网络上求最小费用流。

    建图时俩个点直接连2条边,一条容量为f[i],费用为0,另一条容量为inf,费用为c[i].这样就可以跑俩个算法了

    第二问设一个虚拟源点S与1连容量为k,费用为0的边,n与一个虚拟汇点T连容量为k,费用为0的边。这样一直跑,最后只会增加k的流量。

    记住bool一定要用true和false,用0和1tle了。。不知道为啥,但一定要记住

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 2000 + 10;
    const int maxm = 40000 + 10;
    const int INF = 0x3f3f3f3f;
    
    int n,m,k,eid = -1,S,T,vnum,l,r;
    int v[maxm],f[maxm],c[maxm],next[maxm];
    int h[maxn],d[maxn],gap[maxn],q[maxn],pre[maxn];
    bool inque[maxn];
    
    void add(int a,int b,int F,int C) {
        v[++eid] = b; f[eid] = F; c[eid] = C; next[eid] = h[a]; h[a] = eid;
        v[++eid] = a; f[eid] = 0; c[eid] = -C; next[eid] = h[b]; h[b] = eid;
    }
    
    int ISAP(int u,int flow) {
        if(u == T) return flow;
        
        int cur = 0,aug,mindist = vnum;
        for(int i = h[u]; ~i; i = next[i]) 
            if(f[i] && !c[i] && d[v[i]] + 1 == d[u]) {
                aug = ISAP(v[i],min(f[i],flow-cur));
                f[i] -= aug;
                f[i^1] += aug;
                cur += aug;
                if(cur == flow || d[S] >= vnum) return cur;
            }
        if(!cur) {
            if(!--gap[d[u]]) {
                d[S] = vnum;
                return cur;
            }
            for(int i = h[u]; ~i; i = next[i]) if(f[i] && !c[i])
                mindist = min(mindist,d[v[i]]);
            ++gap[d[u]=mindist+1];
        }
        return cur;
    }
    
    int max_flow() {
        int res = 0;
        gap[0] = vnum = n;
        S = 1; T = n;
        while(d[S] < vnum) 
            res += ISAP(S,INF);
        return res;
    }
    
    void build() {
        scanf("%d%d%d",&n,&m,&k);
        memset(h,-1,sizeof(h));
        for(int i = 1,a,b,f,c; i <= m ; i++) {
            scanf("%d%d%d%d",&a,&b,&f,&c);
            add(a,b,f,0);
            add(a,b,INF,c);
        }
    }
    
    bool spfa() {
        for(int i = 1; i <= T; i++) d[i] = INF;
        l =0,r = 0;
        int u;
        d[S] = 0; inque[q[r++] = S] = true;
        while(l < r) {
            inque[u = q[l++]] = false;
            for(int i = h[u]; ~i ; i = next[i]) 
                if(f[i] && d[v[i]] > d[u] + c[i]) {
                    d[v[i]] = d[u] + c[i];
                    pre[v[i]] = i;
                    if(!inque[v[i]]) inque[q[r++]=v[i]] = true;
                }
        }
        
        return (d[T] < INF);
    }
    
    int augment() {
        int aug = INF,res = 0;
        for(int i = T; i != S; i = v[pre[i]^1]) {
            aug = min(aug,f[pre[i]]);
        }
        
        for(int i = T; i != S; i = v[pre[i]^1]) {
            f[pre[i]] -= aug;
            f[pre[i]^1] += aug;
            res += c[pre[i]]*aug;
        }
        return res;
    }
    
    int cost_flow() {
        int res = 0;
        S = n+1; T = n+2;
        add(S,1,k,0);
        add(n,T,k,0);
        while(spfa()) 
            res += augment();
        return res;
    }
    
    void sovle() {
        printf("%d ",max_flow());
        printf("%d
    ",cost_flow());
    }
    
    int main() {
        build();
        sovle();
        return 0;
    }
  • 相关阅读:
    bzoj1098 1301
    bzoj3237
    bzoj3170
    bzoj4008
    一些题解
    bzoj4028
    bzoj3196
    redis学习
    quartz学习
    电商618 压测、优化、降级预案
  • 原文地址:https://www.cnblogs.com/invoid/p/5380169.html
Copyright © 2020-2023  润新知