• 【网络流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
  • 相关阅读:
    day01--计算机硬件基础笔记
    22 Jun 18 Django,ORM
    21 Jun 18 Django,ORM
    20 Jun 18 复习, mysql
    20 Jun 18 Django,ORM
    19 Jun 18 复习, 正则表达式
    19 Jun 18 Django
    15 Jun 18 复习, shutil模块
    15 Jun 18 Django
    14 Jun 18 复习, form表单
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6328384.html
Copyright © 2020-2023  润新知