首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

【网络流24】餐巾

自己没想出来,看题解了QAQ

原题:

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

1≤f,fA,fB≤60,1≤n≤1000

 

最开始的想法是拆点,拆出的两个点中间连需求的边,割掉表示满足需求,右边的点到汇流量无穷费用0,源到左边的点流量无穷费用为买新的的费用表示可以随意买,右边的点到左边标号+a或b的点流量无穷费用为洗的费用表示,搞了大约2h,然后怎么debug都找不出来问题 (ノ`Д′)ノ︵┻━┻

然后跟踪发现这样建图是不对的……因为从右边到左边的流量经理了两个阶段,先买再洗(如果洗多次的话还会更多),所以洗的花费实际上是买+洗的话费,大于直接买的费用,然后就根本不会增广这一条边……

然后发现思路已经转不过来了,想了一段时间无果,然后各种颓,拖到晚上实在不能再拖了就看了题解QAQ

正解是利用每天产生的脏毛巾已经被钦♂定了这一特殊性,拆点,左边表示脏毛巾,右边表示干净的,源到左边流量为需求费用为0表示每天免费产生固定数量的毛巾,然后源到右边流量无穷费用为新买一条的费用表示任意买,脏毛巾到标号+a或b流量无穷费用为清洗一次的费用表示清洗,最后右边的点到汇流量为需求费用为0的来限制流量,割的意义为满足需求

然后闵神和郑州高一神犇stdcall指点,虽然网络流这种东西需要练习,但是自己想的时间太长的话效率会很低,stdcall建议思考时间是0.5-1h

还要提高效率啊……

代码(思路略乱……):

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int read(){int z=0,mark=1;  char ch=getchar();
 8     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
 9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
10     return z*mark;
11 }
12 const int oo=168430090;
13 struct ddd{int next,y,evalue,rev,cost;}e[1100000];  int LINK[510000],ltop=0;
14 inline void insert(int x,int y,int z,int _cost){
15     e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;e[ltop].evalue=z;e[ltop].rev=ltop+1;e[ltop].cost=_cost;
16     e[++ltop].next=LINK[y];LINK[y]=ltop;e[ltop].y=x;e[ltop].evalue=0;e[ltop].rev=ltop-1;e[ltop].cost=-_cost;
17 }
18 int n,a,b,ncost,acost,bcost;  int S,s,t;
19 int dist[510000];
20 int QUEUE[510000],head=0;  bool visited[510000];
21 int last[510000],last_e[510000];
22 bool spfa(){
23     memset(visited,0,sizeof(visited));
24     memset(dist,10,sizeof(dist));
25     QUEUE[head=1]=s;  visited[s]=true;  dist[s]=0;
26     for(int k=1;k<=head;k++){
27         for(int i=LINK[QUEUE[k]];i;i=e[i].next)
28             if(e[i].evalue && dist[QUEUE[k]]+e[i].cost<dist[e[i].y]){
29                 dist[e[i].y]=dist[QUEUE[k]]+e[i].cost;
30                 last[e[i].y]=QUEUE[k],last_e[e[i].y]=i;
31                 if(!visited[e[i].y])  QUEUE[++head]=e[i].y,visited[e[i].y]=true;
32                 //cout<<e[i].evalue<<endl;
33             }
34         visited[QUEUE[k]]=false;
35     }
36     return dist[t]<oo;
37 }
38 int cost_flow(){
39     int bowl=0;
40     while(spfa()){
41         int min_flow=oo;
42         for(int i=t;i!=s;i=last[i])  min_flow=min(min_flow,e[last_e[i]].evalue);
43         for(int i=t;i!=s;i=last[i]){
44             bowl+=e[last_e[i]].cost*min_flow;
45             //cout<<last[i]<<"->"<<i<<" "<<e[last_e[i]].cost*min_flow<<endl;
46             e[last_e[i]].evalue-=min_flow,e[e[last_e[i]].rev].evalue+=min_flow;
47         }
48     }
49     return bowl;
50 }
51 int main(){freopen("ddd.in","r",stdin);
52     cin>>n>>a>>b>>ncost>>acost>>bcost;  S=n;  s=0,t=S<<1;
53     for(int i=1;i<=n;i++)  insert(i,S+i,read(),0),insert(S+i,t,oo,0);
54     for(int i=1;i<=n;i++){
55         insert(s,i,oo,ncost);
56         for(int j=i+a+1;j<=n;j++)  insert(S+i,j,oo,acost-ncost);
57         for(int j=i+b+1;j<=n;j++)  insert(S+i,j,oo,bcost-ncost);
58     }
59     cout<<cost_flow()<<endl;
60     return 0;
61 }
View Code

 

posted on 2017-01-20 21:31  cdcq_old  阅读(179)  评论(0编辑  收藏  举报