ZOJ3229 有源汇上下界最大流

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3229

题意:报社给M个妹子拍照,并且拍照N天,每一天给给定的C个妹子拍照,每天拍照数量不能超过D张,并且给每个妹子拍照的数量有限制(l,r),所有妹子n天总共拍的照片不能小于Gi张,求最多可以拍多少张照以及拍照方案

题意里这么多限制条件,考虑建图用上下界网络流做。

模型:设置一个起点对每一天连一条[0,D]的边,每一天向对应的被拍照的妹子连一条(l,r)的边,然后设置一个终点,将每个妹子向终点连一条(G,INF)的边

当然建图不是这么建,在上述模型上用有源汇的最大流就可以了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 5010;
const int maxm = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int a[maxn],F[maxm];
struct dinic{
    struct Edge{
        int to,next,cap,flow,id;
        Edge(){}
        Edge(int to,int next,int cap,int flow,int id):
            to(to),next(next),cap(cap),flow(flow),id(id){}
    }edge[maxm * 2];
    int head[maxn],tot,cur[maxn],s,t,n,dep[maxn];
    void init(int n){
        this->n = n;
        for(int i = 0 ; i <= n ; i ++) head[i] = -1;
        tot = 0;
    }
    void add(int u,int v,int w,int id){
        edge[tot] = Edge(v,head[u],w,0,id);
        head[u] = tot++;
        edge[tot] = Edge(u,head[v],0,0,id);
        head[v] = tot++;
    }
    inline bool bfs(){
        for(int i = 0 ; i <= n ; i ++) dep[i] = -1;
        dep[s] = 1;
        queue<int>Q; Q.push(s);
        while(!Q.empty()){
            int u = Q.front(); Q.pop();
            for(int i = head[u]; ~i ; i = edge[i].next){
                int v = edge[i].to;
                if(~dep[v] || edge[i].flow >= edge[i].cap) continue;
                dep[v] = dep[u] + 1;
                Q.push(v);
            }
        }
        return ~dep[t];
    }
    inline int dfs(const int &u,int a){
        if(u == t || !a) return a;
        int flow = 0;
        for(int &i = cur[u];~i ; i = edge[i].next){
            int v = edge[i].to;
            if(dep[v] != dep[u] + 1) continue;
            int f = dfs(v,min(a,edge[i].cap - edge[i].flow));
            flow += f; a -= f;
            edge[i].flow += f;
            edge[i ^ 1].flow -= f;
            //cout << a<< endl;
            if(!a)    return flow;    
        }
        return flow;
    }
    int maxflow(int s,int t){
        this->s = s; this->t = t;
        int flow = 0;
        while(bfs()){
            for(int i = 0 ;i <= n ; i ++) cur[i] = head[i];
            flow += dfs(s,INF);
        }
        return flow;
    }
    void solve(){
        for(int i = 0; i <= n ; i ++){
            for(int j = head[i]; ~j ; j = edge[j].next){
                int v = edge[j].to;
                if(edge[j].flow > 0) F[edge[j].id] = edge[j].flow;
            }
        }
    }
    void del(int S,int T,int SS,int TT){
        for(int i = head[T]; ~i; i = edge[i].next){
            if(edge[i].cap == INF){
                edge[i].cap = edge[i].flow = 0;
                edge[i ^ 1].cap = edge[i ^ 1].flow = 0;
                break;
            }
        }
        for(int i = head[SS]; ~i; i = edge[i].next){
            edge[i].cap = edge[i].flow = 0;
            edge[i ^ 1].cap = edge[i ^ 1].flow = 0;
        }
        for(int i = head[TT]; ~i; i = edge[i].next){
            edge[i].cap = edge[i].flow = 0;
            edge[i ^ 1].cap = edge[i ^ 1].flow = 0;
        }
    }
}g;
int e[maxm];
int main(){
    while(~Sca2(N,M)){
        for(int i = 0; i <= N + M + 4; i ++)a[i] = 0;
        int s = M + N + 1,t = N + M + 2;
        int SS = N + M + 3,TT = N + M + 4;
        g.init(N + M + 4);
        for(int i = 1; i <= M ; i ++){
            int G; Sca(G);
            g.add(N + i,t,INF - G,0);
            a[t] -= G; a[N + i] += G;
        }
        int cnt = 0;
        for(int i = 1; i <= N ; i ++){
            int c,d; Sca2(c,d);
            g.add(s,i,d,0);
            for(int j = 1; j <= c; j ++){
                int id,l,r; Sca3(id,l,r);
                id = id + 1 + N;
                g.add(i,id,r - l,++cnt);
                e[cnt] = l;
                a[id] -= l; a[i] += l;
            }
        }
        for(int i = 0 ; i <= cnt + 1; i ++) F[i] = 0;
        g.add(t,s,INF,cnt + 1);
        int sum = 0;
        for(int i = 1; i <= N + M + 2; i ++){
            if(a[i] > 0){
                g.add(i,TT,a[i],0);
                sum += a[i];
            }else if(a[i] < 0){
                g.add(SS,i,-a[i],0);
            }
        }
        if(sum != g.maxflow(SS,TT)){
            puts("-1");
        }else{
            g.solve();
            g.del(s,t,SS,TT);
            int ans = g.maxflow(s,t) + F[cnt + 1];
            Pri(ans);
            g.solve();
            for(int i = 1; i <= cnt; i ++){
                Pri(F[i] + e[i]);
            }
        } 
        puts("");
    } 
    return 0;
}
原文地址:https://www.cnblogs.com/Hugh-Locke/p/11146502.html