• BZOJ2465: [中山市选2009]小球


    Description

           给定n个不同颜色的球,每个球都有一个分数,同时有m个瓶子,每个瓶子都有固定的容量。现在,你必须把球放到瓶子里面。请编程计算最多能放多少个球到这些瓶子里。

    Input

    输入包含多组数据。
    每组数据的第一行为两个整数n, m,分别表示球的个数和瓶子的个数。
    接下来的n行,每一行包含一个整数p,表示相应的球的分数。
    接下来的m行,每一行包含两个整数c和q, 分别表示每个瓶子的容量(最多能装多少个球)和分数上界(放进该瓶子的每个球的分数都不能超过去q)。
    当输入n,m均为0时,表示输入结束。

    Output

    对于每组数据,输出两个整数B和S,分别表示总共能放进瓶子里的球的最大数目,以及在这个前提下,放进瓶子里面的所有球的最大分数总和。B和S以空格隔开,每组答案独占一行。

    Sample Input

    2 1
    2
    3
    1 2
    2 2
    4
    5
    2 4
    2 5
    0 0

    Sample Output

    1 2
    2 9

    HINT

    对于全部的数据,有1<=n<=2000<=m<=2001 <= p <= 10^6, 0 <= c <= 200, 1 <= q <= 10^6.

    看来只有我这样的doubi才会萌萌哒地写费用流。

    直接上ZKW费用流,将小球和盒子分别按分数排序,填上一些边。。。

    模板一遍打对还是很开心的。

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int inf=1000000000;
    const int maxn=510;
    const int maxm=20010;
    struct ZKW {
        int n,m,s,t,inq[maxn],d[maxn];
        int first[maxn],next[maxm];
        struct Edge {int from,to,flow,cost;}edges[maxm];
        ll cost,ans;
        void init(int n) {
            this->n=n;m=0;
            memset(first,-1,sizeof(first));
        }
        void AddEdge(int u,int v,int w,int cost) {
            edges[m]=(Edge){u,v,w,cost};next[m]=first[u];first[u]=m++;
            edges[m]=(Edge){v,u,0,-cost};next[m]=first[v];first[v]=m++;
        }
        int Q[maxn*100],vis[maxn];
        int BFS() {
            rep(i,1,n) d[i]=inf;d[t]=0;
            int l=1,r=0;Q[++r]=t;
            while(l<=r) {
                int x=Q[l++];inq[x]=0;
                ren {
                    Edge& e=edges[i^1];
                    if(e.flow&&d[e.from]>d[x]+e.cost) {
                        d[e.from]=d[x]+e.cost;
                        if(!inq[e.from]) inq[e.from]=1,Q[++r]=e.from;
                    }
                }
            }
            rep(i,0,m-1) edges[i].cost+=d[edges[i].to]-d[edges[i].from];
            cost+=d[s];return d[s]!=inf;
        }
        int DFS(int x,int a) {
            if(x==t||!a) {ans+=a*cost;return a;}
            int f,flow=0;vis[x]=1;
            ren {
                Edge& e=edges[i];
                if(e.flow&&!e.cost&&!vis[e.to]&&(f=DFS(e.to,min(a,e.flow)))) {
                    e.flow-=f;edges[i^1].flow+=f;
                    flow+=f;a-=f;if(!a) break;
                }
            }
            return flow;
        }
        void solve(int s,int t) {
            this->s=s;this->t=t;
            cost=ans=0;int flow=0,tmp;
            while(BFS()) do {
                memset(vis,0,sizeof(vis));
                flow+=(tmp=DFS(s,inf));
            }while(tmp);
            printf("%d %lld
    ",flow,-ans);
        }
    }sol;
    int A[maxn];
    struct Bottle {
        int c,q;
        bool operator < (const Bottle& ths) const {return q>ths.q;}
    }B[maxn];
    int main() {
        while(1) {
            int n=read(),m=read(),s=n+m+1,t=n+m+2;sol.init(n+m+2);
            if(!n&&!m) break;
            rep(i,1,n) A[i]=read();
            rep(i,1,m) B[i].c=read(),B[i].q=read();
            sort(A+1,A+n+1);sort(B+1,B+m+1);
            rep(i,1,n) {
                sol.AddEdge(s,i,1,-A[i]);
                int j=1;while(j<=m&&B[j].q>=A[i]) j++;
                if(j!=1) sol.AddEdge(i,j+n-1,1,0);
            }
            rep(i,1,m) {
                if(i!=1) sol.AddEdge(i+n,i+n-1,inf,0);
                sol.AddEdge(i+n,t,B[i].c,0);
            }
            sol.solve(s,t);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    bzoj 4446: [Scoi2015]小凸玩密室【树形dp】
    bzoj 4403: 序列统计【lucas+组合数学】
    bzoj 3745: [Coci2015]Norma【分治】
    bzoj 3232: 圈地游戏【分数规划+最小割】
    Codeforces 1000 (A~E)
    bzoj 4753: [Jsoi2016]最佳团体【01分数规划+二分+树上背包】
    bzoj 3872: [Poi2014]Ant colony【树形dp+二分】
    bzoj 2067: [Poi2004]SZN【贪心+二分+树形dp】
    洛谷 P1314 聪明的质监员【二分+前缀和】
    bzoj 4622: [NOI 2003] 智破连环阵【dfs+匈牙利算法】
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5035064.html
Copyright © 2020-2023  润新知