BZOJ 3280: 小R的烦恼 & BZOJ 1221: [HNOI2001] 软件开发

Posted NeighThorn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3280: 小R的烦恼 & BZOJ 1221: [HNOI2001] 软件开发相关的知识,希望对你有一定的参考价值。

3280: 小R的烦恼

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 399  Solved: 200
[Submit][Status][Discuss]

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.

Source

网络流

分析:

我们把每一天拆成两个点,一个叫做A集合,一个叫做B集合...从S向A集合的每个点连一条容量为a[i]费用为0的边,从B集合中的每个点向T连边...

然后对于每个大学,从当前大学向每个B集合中的点连一条容量为inf费用为0的边,从S向每个大学连一条容量为l[i]费用为p[i]的边...

然后A集合中的每个点向B集合中的对应点+d[x]+1的点连一条容量为inf费用为q[x]的边,然后每个B集合中的点向下一天的点连边...

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<queue>
 6 //by NeighThorn
 7 #define inf 0x3f3f3f3f
 8 using namespace std;
 9  
10 const int maxn=200+5,maxm=20000+5;
11  
12 int c,n,m,k,S,T,ans,sum,cas,cnt,w[maxm],hd[maxn],fl[maxm],to[maxm],nxt[maxm],dis[maxn],Min[maxn],vis[maxn],from[maxn];
13  
14 inline bool spfa(void){
15     memset(dis,inf,sizeof(dis));
16     memset(Min,inf,sizeof(Min));
17     queue<int> q;q.push(S),vis[S]=1,dis[S]=0;
18     while(!q.empty()){
19         int top=q.front();q.pop();vis[top]=0;
20         for(int i=hd[top];i!=-1;i=nxt[i])
21             if(dis[to[i]]>dis[top]+w[i]&&fl[i]){
22                 from[to[i]]=i;
23                 dis[to[i]]=dis[top]+w[i];
24                 Min[to[i]]=min(Min[top],fl[i]);
25                 if(!vis[to[i]])
26                     vis[to[i]]=1,q.push(to[i]);
27             }
28     }
29     return dis[T]!=inf;
30 }
31  
32 inline int find(void){
33     for(int i=T;i!=S;i=to[from[i]^1])
34         fl[from[i]]-=Min[T],fl[from[i]^1]+=Min[T];
35     return ans+=Min[T],dis[T]*Min[T];
36 }
37  
38 inline int mcmf(void){
39     int res=0;
40     while(spfa())
41         res+=find();
42     return res; 
43 }
44  
45 inline void add(int l,int s,int x,int y){//cout<<x<<" "<<y<<" "<<s<<" "<<l<<endl;
46     w[cnt]=l;fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
47     w[cnt]=-l;fl[cnt]=0;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++;   
48 }
49  
50 signed main(void){
51     scanf("%d",&cas);
52     while(cas--){cnt=0;c++;sum=ans=0;
53         scanf("%d%d%d",&n,&m,&k);S=0;
54         memset(hd,-1,sizeof(hd));T=n*2+m+1;
55         for(int i=1,x;i<=n;i++){
56             scanf("%d",&x),add(0,x,S,i+n),add(0,x,i,T);sum+=x;
57             if(i+1<=n)
58                 add(0,inf,i,i+1);
59         }
60         for(int i=1,x,y;i<=m;i++){
61             scanf("%d%d",&x,&y),add(y,x,S,2*n+i);
62             for(int j=1;j<=n;j++)
63                 add(0,inf,2*n+i,j);
64         }
65         for(int i=1,x,y;i<=k;i++){
66             scanf("%d%d",&x,&y);x++;
67             for(int j=1;j<=n;j++){
68                 int lala=j+x;
69                 if(lala<=n)
70                     add(y,inf,j+n,lala);
71             }
72         }int lala=mcmf();
73         printf("Case %d: ",c);
74         if(ans!=sum)
75             puts("impossible");
76         else
77             printf("%d\\n",lala);
78     }
79     return 0;   
80 }

 

1221: [HNOI2001] 软件开发

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1454  Solved: 805
[Submit][Status][Discuss]

Description

某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消毒毛巾,这种消毒毛巾使用一天后必须再做消毒处理后才能使用。消毒方式有两种,A种方式的消毒需要a天时间,B种方式的消毒需要b天(b>a),A种消毒方式的费用为每块毛巾fA, B种消毒方式的费用为每块毛巾fB,而买一块新毛巾的费用为f(新毛巾是已消毒的,当天可以使用);而且f>fA>fB。公司经理正在规划在这n天中,每天买多少块新毛巾、每天送多少块毛巾进行A种消毒和每天送多少块毛巾进行B种消毒。当然,公司经理希望费用最低。你的任务就是:为该软件公司计划每天买多少块毛巾、每天多少块毛巾进行A种消毒和多少毛巾进行B种消毒,使公司在这项n天的软件开发中,提供毛巾服务的总费用最低。

Input

第1行为n,a,b,f,fA,fB. 第2行为n1,n2,……,nn. (注:1≤f,fA,fB≤60,1≤n≤1000)

Output

最少费用

Sample Input

4 1 2 3 2 1
8 2 1 6

Sample Output

38

HINT

Source

分析:

和上一题差不多...

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<queue>
 6 //by NeighThorn
 7 #define inf 0x3f3f3f3f
 8 using namespace std;
 9  
10 const int maxn=2000+5,maxm=maxn*maxn;
11  
12 int n,a,b,f,fa,fb,S,T,cnt,w[maxm],hd[maxn],to[maxm],fl[maxm],nxt[maxm],dis[maxn],Min[maxn],vis[maxn],from[maxn];
13  
14 inline bool spfa(void){
15     memset(dis,inf,sizeof(dis));
16     memset(Min,inf,sizeof(Min));
17     queue<int> q;q.push(S),vis[S]=1,dis[S]=0;
18     while(!q.empty()){
19         int top=q.front();q.pop();vis[top]=0;
20         for(int i=hd[top];i!=-1;i=nxt[i])
21             if(dis[to[i]]>dis[top]+w[i]&&fl[i]){
22                 from[to[i]]=i;
23                 dis[to[i]]=dis[top]+w[i];
24                 Min[to[i]]=min(Min[top],fl[i]);
25                 if(!vis[to[i]])
26                     vis[to[i]]=1,q.push(to[i]);
27             }
28     }
29     return dis[T]!=inf;
30 }   
31  
32 inline int find(void){
33     for(int i=T;i!=S;i=to[from[i]^1])
34         fl[from[i]]-=Min[T],fl[from[i]^1]+=Min[T];
35     return dis[T]*Min[T];   
36 }
37  
38 inline int mcmf(void){
39     int res=0;
40     while(spfa())
41         res+=find();
42     return res; 
43 }
44  
45 inline void add(int l,int s,int x,int y){
46     w[cnt]=l;fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
47     w[cnt]=-l;fl[cnt]=0;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++;
48 }
49  
50 signed main(void){
51     memset(hd,-1,sizeof(hd));S=0;
52     scanf("%d%d%d%d%d%d",&n,&a,&b,&f,&fa,&fb);T=2*n+1;
53     for(int i=1,x;i<=n;i++){
54         scanf("%d",&x),add(0,x,S,i),add(0,x,i+n,T);
55         if(i<n)
56             add(0,inf,i+n,i+n+1);
57         int lala=i+a+1,lalala=i+b+1;
58         if(lala<=n)
59             add(fa,inf,i,lala+n);
60         if(lalala<=n)
61             add(fb,inf,i,lalala+n);
62     }add(f,inf,S,1+n);
63     printf("%d\\n",mcmf());
64     return 0;
65 }//Cap ou pas cap. Pas cap.
66 

 




By NeighThorn

以上是关于BZOJ 3280: 小R的烦恼 & BZOJ 1221: [HNOI2001] 软件开发的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3280: 小R的烦恼

bzoj3280小R的烦恼 费用流

食物(bzoj 3280)

bzoj3280

bzoj千题计划143:bzoj1935: [Shoi2007]Tree 园丁的烦恼

[BZOJ]1005 明明的烦恼(HNOI2008)