zoukankan      html  css  js  c++  java
  • bzoj3280: 小R的烦恼

    Description

    小R最近遇上了大麻烦,他的程序设计挂科了。于是他只好找程设老师求情。善良的程设老师答应不挂他,但是要求小R帮助他一起解决一个难题。
    问题是这样的,程设老师最近要进行一项邪恶的实验来证明P=NP,这个实验一共持续n天,第i天需要a[i]个研究生来给他搬砖。研究生毕竟也是人,所以雇佣研究生是需要钱的,机智的程设老师已经联系好了m所大学,第j所大学共有l[j]个研究生,同时雇佣这所大学的一个研究生需要p[j]元钱。
    本来程设老师满心欢喜的以为,这样捡最便宜的max{a[i]}个研究生雇来,就可以完成实验;结果没想到,由于他要求硕士生们每天工作25个小时不许吃饭睡觉上厕所喝水说话咳嗽打喷嚏呼吸空气,因此一天下来给他搬砖的所有研究生都会进入濒死状态。濒死状态的研究生,毫无疑问,就不能再进行工作了。但是机智的老师早早联系好了k家医院,第i家医院医治一个濒死的研究生需要d[i]天,并且需要q[i]元钱。

    现在,程设老师想要知道,最少花多少钱,能够在这n天中满足每天的需要呢?若无法满足,则请输出”impossible”。注意,由于程设老师良心大大的坏,所以他是可以不把濒死的研究生送去医院的!

    
    
     

    Input

           本题包含多组数据;第一行是一个数T(T<=11),表示数据组数,以下T组数据。
    对于每一组数据,第一行三个数,n,m,k;
    以下一行n个数,表示a[1]…a[n]
    接着一行2m个数,表示l[1],p[1]…l[n],p[n]
    接着一行2k个数,表示d[1],q[1]…d[n],q[n]

    Output

           对于每组数据以样例的格式输出一行,两个数分别表示第几组数据和最少钱数。

    Sample Input

    2
    3 2 1
    10 20 30
    40 90 15 100
    1 5
    3 2 1
    10 20 30
    40 90 15 100
    2 5

    Sample Output

    Case 1: 4650
    Case 2: impossible

    HINT

    样例解释:买下90块钱的那40个研究生,另外再买10个100块钱的。这样,第一天用完的10个人全部送到医院,那么他们在第三天可以继续使用;同时,第二天和第三天都用新的研究生来弥补,这样一共需要花费40*90 + 10*100 + 5*10 = 4650元。

    数据规模:

    对于30%的数据中的每组数据,

    满足n<=5,m,k<=2,其余数均小于等于100或者

    n<=10,m,k<=10,其余数均小于等于20.

    对于100%的数据

    n,m,k<=50,其余数均小于等于100.

     
    题解:
    先要将每一天拆成两个点分别表示这天开始和结束
    由S向第一天的开始练m条边,容量和费用分别为每个学校的学生个数和单价,表示要买多少学生和所需的费用
    由每天开始向T连容量为每天所需的学生个数,费用为0,表示这天要用这么多的学生
    由每天开始向下一天开始连容量为inf,费用为0的边,表示这天没有用到的学生可以留到下一天用
    由S向每天的结束连容量为每天所需的学生个数,费用为0,表示这天用过的并且要去复活的学生
    对于每个医院(d,q),由第i天的结束节点向第i+d+1天的开始节点连容量为inf,费用为q的边,表示把这些学生复活
    然后跑遍费用流即可,如果最大流=总共所需学生数量则有解,否则无解
    code:
     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #define maxn 105
     7 #define maxm 20300
     8 #define inf 1061109567
     9 using namespace std;
    10 char ch;
    11 bool ok;
    12 void read(int &x){
    13     ok=0;
    14     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
    15     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
    16     if (ok) x=-x;
    17 }
    18 int T,n,m,k,x,y,sum;
    19 struct costflow{
    20     int s,t,tot,now[maxn],son[maxm],pre[maxm],val[maxm],cost[maxm];
    21     int dis[maxn],tmp,totflow,totcost,sla[maxn],head,tail,list[maxn],path[maxn];
    22     bool bo[maxn];
    23     void init(){s=0,t=(n<<1)+1,tot=1,memset(now,0,sizeof(now));}
    24     void put(int a,int b,int c,int d){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c,cost[tot]=d;}
    25     void add(int a,int b,int c,int d){put(a,b,c,d),put(b,a,0,-d);}
    26     int dfs(int u,int rest,int totval){
    27         if (u==t){totcost+=rest*totval;return rest;}
    28         int ans=0; bo[u]=1;
    29         for (int p=now[u],v=son[p];p&&rest;p=pre[p],v=son[p])
    30             if (val[p]&&!bo[v]){
    31                 int t=dis[u]+cost[p]-dis[v];
    32                 if (!t){
    33                     int d=dfs(v,min(rest,val[p]),totval+cost[p]);
    34                     val[p]-=d,val[p^1]+=d,ans+=d,rest-=d;
    35                 }
    36                 else sla[v]=min(sla[v],t);
    37             }
    38         return ans;
    39     }
    40     bool relax(){
    41         int d=inf;
    42         for (int u=s;u<=t;u++) if (!bo[u]) d=min(d,sla[u]);
    43         if (d==inf) return false;
    44         for (int u=s;u<=t;u++) if (!bo[u]) dis[u]+=d;
    45         return true;    
    46     }
    47     void work(){
    48         memset(dis,0,sizeof(dis)),totflow=totcost=0;
    49         do{
    50             memset(sla,63,sizeof(sla));
    51             do{
    52                 memset(bo,0,sizeof(bo));
    53                 tmp=dfs(s,inf,0),totflow+=tmp;
    54             }while (tmp);
    55         }while (relax());
    56     }
    57 }f;
    58 int main(){
    59     int Case=0;
    60     for (read(T);T;T--){
    61         read(n),read(m),read(k),f.init(),sum=0,Case++;
    62         for (int i=1;i<=n;i++) read(x),sum+=x,f.add(i,f.t,x,0),f.add(f.s,i+n,x,0);
    63         for (int i=1;i<n;i++) f.add(i,i+1,inf,0);
    64         for (int i=1;i<=m;i++) read(x),read(y),f.add(f.s,1,x,y);
    65         for (int i=1;i<=k;i++){
    66             read(x),read(y);
    67             for (int j=1;j<=n-x-1;j++) f.add(j+n,j+x+1,inf,y);
    68         }
    69         f.work();
    70         printf("Case %d: ",Case);
    71         if (f.totflow==sum) printf("%d
    ",f.totcost);
    72         else puts("impossible");
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    【PBR的基本配置】
    【super vlan的配置】
    Day_03-函数和模块的使用
    Day_02-Python的循环结构
    Day_02-Python的分支结构和循环结构
    Day01_课后练习题
    Day01_初识Python
    一、Linux知识体系结构图
    NAND Flash结构及驱动函数
    区分大端和小端
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5152605.html
Copyright © 2011-2022 走看看