[bzoj1221]软件开发

记源点为S,汇点为T,第i天裂成两个点,分别是i1和i2,表示剩余的毛巾(都是脏毛巾,因为一定可以做到每天不剩余干净的毛巾)和使用的毛巾(用来保证最大流符合条件),然后考虑以下边:
1.S向每一个i1连一条(ni,0)的边,表示用过的毛巾;
2.i2向每一个T连一条(ni,0)的边,表示消耗毛巾;
3.每一个i1向(i+1)1连一条(inf,0)的边,表示剩余毛巾的传递;
4.S向每一个i2连一条(ni/inf,F)的边,表示买毛巾;
5.每一个i1向(i+a+1)2连一条(inf,Fa)的边,表示用a方法洗毛巾;
6.每一个i1向(i+b+1)2连一条(inf,Fb)的边,表示用b方法洗毛巾。
这样就可以处理好所有问题,跑最小费用最大流即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 2005
 4 #define oo 0x3f3f3f3f
 5 struct ji{
 6     int nex,to,len,cost;
 7 }edge[N*10];
 8 queue<int>q;
 9 int E,n,a,b,f,fa,fb,t,head[N],from[N],d[N],vis[N];
10 void add(int x,int y,int z,int w){
11     edge[E].nex=head[x];
12     edge[E].to=y;
13     edge[E].len=z;
14     edge[E].cost=w;
15     head[x]=E++;
16     if (E&1)add(y,x,0,-w);
17 }
18 bool spfa(){
19     memset(vis,0,sizeof(vis));
20     memset(d,oo,sizeof(d));
21     d[0]=0;
22     q.push(0);
23     while (!q.empty()){
24         int k=q.front();
25         q.pop();
26         vis[k]=0;
27         for(int i=head[k];i!=-1;i=edge[i].nex){
28             int v=edge[i].to;
29             if ((edge[i].len)&&(d[v]>d[k]+edge[i].cost)){
30                 d[v]=d[k]+edge[i].cost;
31                 from[v]=i;
32                 if (!vis[v]){
33                     vis[v]=1;
34                     q.push(v);
35                 }
36             }
37         }
38     }
39     return d[t]<oo;
40 }
41 int dinic(){
42     int ans=0;
43     while (spfa()){
44         int len=oo;
45         for(int i=t;i;i=edge[from[i]^1].to)len=min(len,edge[from[i]].len);
46         ans+=len*d[t];
47         for(int i=t;i;i=edge[from[i]^1].to){
48             edge[from[i]].len-=len;
49             edge[from[i]^1].len+=len;
50         }
51     }
52     return ans;
53 }
54 int main(){
55     scanf("%d%d%d%d%d%d",&n,&a,&b,&f,&fa,&fb);
56     memset(head,-1,sizeof(head));
57     for(int i=1;i<=n;i++){
58         scanf("%d",&t);
59         add(0,i,t,0);
60         add(0,i+n,t,f);
61         add(i+n,2*n+1,t,0);
62         if (i<n)add(i,i+1,oo,0);
63         if (i+a<n)add(i,i+a+n+1,oo,fa);
64         if (i+b<n)add(i,i+b+n+1,oo,fb);
65     }
66     t=2*n+1; 
67     printf("%d",dinic());
68 }
View Code

 

posted @ 2019-08-15 13:30  PYWBKTDA  阅读(132)  评论(0编辑  收藏  举报