zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    关于求 p_i != i and p_i != i+1 的方案数的思考过程
    poj 3041 Asteroids 二分图最小覆盖点
    poj 1325 Machine Schedule 最小顶点覆盖
    poj 1011 Sticks 减枝搜索
    poj 1469 COURSES 最大匹配
    zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
    Path Cover (路径覆盖)
    hdu 3530 SubSequence TwoPoint单调队列维护最值
    zoj 1654 Place the Rebots 最大独立集转换成二分图最大独立边(最大匹配)
    poj 1466 Girls and Boys 二分图最大独立子集
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/11146502.html
Copyright © 2011-2022 走看看