【中学高级本-网络流24题】餐巾计划

把每天分为二分图两个集合中的顶点Xi,Yi,建立附加源ST
1、从S向每个Xi连一条容量为ri,费用为0的有向边。
表示第i天还剩ri条餐巾。
2、从每个YiT连一条容量为ri,费用为0的有向边。
控制最大流
3、从S向每个Yi连一条容量为无穷大,费用为p的有向边。
表示买餐巾
4、从每个XiXi+1(i+1<=N)连一条容量为无穷大,费用为0的有向边。
表示第i天剩的餐巾可以留给第i+1天。
5、从每个XiYi+m(i+m<=N)连一条容量为无穷大,费用为f的有向边。
表示快洗
6、从每个XiYi+n(i+n<=N)连一条容量为无穷大,费用为s的有向边。
表示慢洗
然后就求最小费用最大流就可以了
 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<ctime>
 6 #include<cmath>
 7 #include<string>
 8 #include<vector>
 9 #include<cstdio>
10 #include<cstdlib>
11 #include<cstring>
12 #include<iostream>
13 #include<algorithm>
14 #define inf 1999999999
15 using namespace std;
16 struct data{
17   int nex,to,w,c;
18 }e[2610];
19 int head[410],edge=-1,dis[410],vis[410],pre[410];
20 void add(int from,int to,int w,int c){
21   e[++edge].nex=head[from];
22   e[edge].to=to;
23   e[edge].w=w;
24   e[edge].c=c;
25   head[from]=edge;
26 }
27 inline int SPFA(int s,int t){
28   queue<int>q;
29   q.push(s);
30   memset(dis,127,sizeof(dis));int zd=dis[0];
31   memset(vis,0,sizeof(vis));
32   dis[s]=0,vis[s]=1;
33   while(!q.empty()){
34     int u=q.front();q.pop();
35     vis[u]=0;
36     for(int i=head[u];i!=-1;i=e[i].nex){
37       int v=e[i].to;
38       if(e[i].w>0 && dis[v]>dis[u]+e[i].c){
39     dis[v]=dis[u]+e[i].c;
40     pre[v]=i;
41     if(!vis[v])q.push(v),vis[v]=1;
42       }
43     }
44   }
45   if(dis[t]==zd) return 0;
46   else return 1;
47 }
48 inline int end(int s,int t){
49   int ans=0,p=0,sum=inf;
50   for(int u=t;u!=s;u=e[p^1].to)
51     p=pre[u],sum=min(sum,e[p].w);
52   for(int u=t;u!=s;u=e[p^1].to){
53     p=pre[u];
54     e[p].w-=sum;
55     e[p^1].w+=sum;
56     ans+=e[p].c*sum;
57   }
58   return ans;
59 }
60 inline int solve(int s,int t){
61   int flow=0;
62   while(SPFA(s,t)) flow+=end(s,t);
63   return flow;
64 }
65 int main()
66 {
67   freopen("!.in","r",stdin);
68   freopen("!.out","w",stdout);
69   memset(head,-1,sizeof(head));
70   int n,p,k,fk,m,fm,x;
71   scanf("%d",&n);int s=0,t=2*n+1;
72   for(int i=1;i<=n;i++)
73     scanf("%d",&x),add(s,i,x,0),add(i,s,0,0),add(i+n,t,x,0),add(t,i+n,0,0);
74   scanf("%d%d%d%d%d",&p,&k,&fk,&m,&fm);
75   for(int i=2;i<=n;i++)
76     add(i-1,i,inf,0),add(i,i-1,0,0);
77   for(int i=1;i<=n;i++){
78     if(i-k>0) add(i-k,i+n,inf,fk),add(i+n,i-k,0,-fk);
79     if(i-m>0) add(i-m,i+n,inf,fm),add(i+n,i-m,0,-fm);
80     add(s,n+i,inf,p),add(n+i,s,0,-p);
81   }
82   printf("%d",solve(s,t));
83   return 0;
84 }

 

posted @ 2017-03-23 13:37  嘘丶  阅读(153)  评论(0编辑  收藏  举报