zoukankan      html  css  js  c++  java
  • BZOJ 1391 [Ceoi2008]order

    1391: [Ceoi2008]order

    Description

    有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成。 现在给出这些参数,求最大利润

    Input

    第一行给出 N,M(1<=N<=1200,1<=M<=1200) 下面将有N块数据,每块数据第一行给出完成这个任务能赚到的钱(其在[1,5000])及有多少道工序 接下来若干行每行两个数,分别描述完成工序所需要的机器编号及租用它的费用(其在[1,20000]) 最后M行,每行给出购买机器的费用(其在[1,20000])

    Output

    最大利润

    Sample Input

    2 3
    100 2
    1 30
    2 20
    100 2
    1 40
    3 80
    50
    80
    110

    Sample Output

    50

    HINT


      此题颇为有趣。一看便能知道是最大权闭合子图。但怎么区分租赁与购买呢?做了此题,再与BZOJ 1497 [NOI2006]最大获利比较,一下子我就明白了。

      此题中,n个工作的获益先加在一起。源点S与n个工作连一条流量为获利的边,m台机器与汇点T连一条流量为购买费用的边,工作与机器之间连上相应的租赁费用。这样,跑一遍最大流(最小割),然后sum-maxflow即可。

      为什么是对的?因为租赁可以理解为暂时的专属的,而购买就是永恒的普遍的。这在建图中体现的很明显。

      而NOI那道题中,只不过没有租赁,所以工作与机器之间是inf。

      很有意思啊!

     1 /**************************************************************
     2     Problem: 1391
     3     User: Doggu
     4     Language: C++
     5     Result: Accepted
     6     Time:4252 ms
     7     Memory:47844 kb
     8 ****************************************************************/
     9  
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <algorithm>
    13 template<class T>inline void readin(T &res) {
    14     static char ch;T flag=1;
    15     while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;
    16     res=ch-48;while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;res*=flag;
    17 }
    18  
    19 const int N = 10000;
    20 const int M = 3000000;
    21 struct Edge {int v,upre,cap,flow;}g[M];
    22 int head[N], ne=-1;
    23 inline void adde(int u,int v,int cap) {
    24     g[++ne]=(Edge){v,head[u],cap,0};head[u]=ne;
    25     g[++ne]=(Edge){u,head[v],0,0};head[v]=ne;
    26 }
    27  
    28 #include <queue>
    29 std::queue<int> q;
    30 int n, m, s, t, sum, d[N], cur[N];
    31 bool BFS() {
    32     while(!q.empty()) q.pop();
    33     memset(d,0,sizeof(d));
    34     q.push(s);d[s]=1;
    35     while(!q.empty()) {
    36         int u=q.front();q.pop();
    37         for( int i = head[u]; i != -1; i = g[i].upre ) {
    38             int v=g[i].v;
    39             if(!d[v]&&g[i].cap>g[i].flow) q.push(v), d[v]=d[u]+1;
    40         }
    41     }
    42     return d[t];
    43 }
    44 int DFS(int u,int a) {
    45     if(u==t||a==0) return a;
    46     int flow=0, f;
    47     for( int &i = cur[u]; i != -1; i = g[i].upre ) {
    48         int v=g[i].v;
    49         if(d[v]==d[u]+1&&(f=DFS(v,std::min(a,g[i].cap-g[i].flow)))>0) {
    50             flow+=f;a-=f;
    51             g[i].flow+=f;g[i^1].flow-=f;
    52             if(a==0) break;
    53         }
    54     }
    55     if(flow==0) d[u]=0;
    56     return flow;
    57 }
    58 void maxflow() {
    59     int flow=0;
    60     while(BFS()) {
    61         memcpy(cur,head,sizeof(head));
    62         flow+=DFS(s,0x3f3f3f3f);
    63     }
    64     printf("%d
    ",sum-flow);
    65 }
    66  
    67 int main() {
    68     memset(head,-1,sizeof(head));
    69     readin(n);readin(m);s=0;t=n+m+1;
    70     for( int i = 1, w, a, b, c; i <= n; i++ ) {
    71         readin(w);readin(b);
    72         adde(s,i,w);sum+=w;
    73         for( int j = 1; j <= b; j++ ) {
    74             readin(a);readin(c);
    75             adde(i,n+a,c);
    76         }
    77     }
    78     for( int i = 1,c; i <= m; i++ ) {
    79         readin(c);
    80         adde(n+i,t,c);
    81     }
    82     maxflow();
    83     return 0;
    84 }
    85 
    dinic最小割建图
  • 相关阅读:
    How to make BBED(Oracle Block Brower and EDitor Tool) on Unix/Linux/Windows
    直接路径读取对于延迟块清除的影响
    Mysql:日志管理:一般查询日志、慢速查询日志的
    Mysql:函数之二: miscellaneous functions
    Mysql:函数之三: date and time functions:重要的格式化函数
    Mysql:日志管理:综述
    Mysql:函数之三: date and time functions
    程序员阿BEN的SOHO生活
    网页常用Javascript
    优秀程序员的十个习惯
  • 原文地址:https://www.cnblogs.com/Doggu/p/bzoj1391.html
Copyright © 2011-2022 走看看