• 【BZOJ 1061】 1061: [Noi2008]志愿者招募 (线性规划与网络流)**


    1061: [Noi2008]志愿者招募

    Description

      申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难
    题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要
    Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用
    是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这
    并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。

    Input

      第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负
    整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了
    方便起见,我们可以认为每类志愿者的数量都是无限多的。

    Output

      仅包含一个整数,表示你所设计的最优方案的总费用。

    Sample Input

    3 3
    2 3 4
    1 2 2
    2 3 5
    3 3 2

    Sample Output

    14

    HINT

    1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。

    Source

    【分析】

      表示初看觉得这题很经典但是仔细想想发现我不会ORZ。。

      表示不会单纯形法搞线性规划【要学么?

      之前做的网络流24题都没有涉及到线性规划的转化的。。

      这道的确是经典题,但是转化挺难的。。

      推荐博客!!https://www.byvoid.com/zhs/blog/noi-2008-employee#more-916

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxn 1010
      9 #define Maxm 10010
     10 #define INF 0xfffffff
     11 
     12 int mymin(int x,int y) {return x<y?x:y;}
     13 
     14 int n,m;
     15 
     16 struct node
     17 {
     18     int x,y,f,c,o,next;
     19 }t[4*Maxm];
     20 int first[Maxn],len;
     21 
     22 void ins(int x,int y,int f,int c)
     23 {
     24     t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;t[len].o=len+1;
     25     t[len].next=first[x];first[x]=len;
     26     t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c;t[len].o=len-1;
     27     t[len].next=first[y];first[y]=len;
     28 }
     29 
     30 int nd[Maxn];
     31 int dis[Maxn],flow[Maxn],pre[Maxn],st,ed;
     32 bool inq[Maxn];
     33 queue<int > q;
     34 
     35 void bfs()
     36 {
     37     while(!q.empty()) q.pop();
     38     // memset(dis,-1,sizeof(dis));
     39     for(int i=1;i<=ed;i++) dis[i]=INF;
     40     memset(inq,0,sizeof(inq));
     41     dis[st]=0;inq[st]=1;q.push(st);
     42     flow[st]=INF;
     43     while(!q.empty())
     44     {
     45         int x=q.front();
     46         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     47         {
     48             int y=t[i].y;
     49             if(dis[y]>dis[x]+t[i].c)
     50             {
     51                 dis[y]=dis[x]+t[i].c;
     52                 pre[y]=i;
     53                 flow[y]=mymin(flow[x],t[i].f);
     54                 if(!inq[y])
     55                 {
     56                     q.push(y);
     57                     inq[y]=1;
     58                 }
     59             }
     60         }
     61         q.pop();inq[x]=0;
     62     }
     63 }
     64 
     65 void max_flow()
     66 {
     67     int sum=0;
     68     while(1)
     69     {
     70         bfs();
     71         if(dis[ed]==INF) break;
     72         sum+=dis[ed]*flow[ed];
     73         int x=ed;
     74         while(x!=st)
     75         {
     76             t[pre[x]].f-=flow[ed];
     77             t[t[pre[x]].o].f+=flow[ed];
     78             x=t[pre[x]].x;
     79         }
     80     }
     81     printf("%d
    ",sum);
     82 }
     83 
     84 void output()
     85 {
     86     for(int i=1;i<=len;i+=2)
     87     {
     88         printf("%d -> %d = %d , %d 
    ",t[i].x,t[i].y,t[i].f,t[i].c);
     89     }
     90 }
     91 
     92 int main()
     93 {
     94     scanf("%d%d",&n,&m);
     95     len=0;
     96     for(int i=1;i<=n;i++) scanf("%d",&nd[i]);
     97     memset(first,0,sizeof(first));
     98     for(int i=1;i<=m;i++)
     99     {
    100         int l,r,c;
    101         scanf("%d%d%d",&l,&r,&c);
    102         ins(l,r+1,INF,c);
    103     }
    104     for(int i=1;i<=n;i++) ins(i+1,i,INF,0);
    105     nd[0]=0;
    106     st=n+2;ed=st+1;
    107     for(int i=1;i<=n;i++) if(nd[i]-nd[i-1]>0) ins(st,i,nd[i]-nd[i-1],0);
    108     else if(nd[i]-nd[i-1]<0) ins(i,ed,nd[i-1]-nd[i],0);
    109     ins(n+1,ed,nd[n],0);
    110     // output();
    111     max_flow();
    112     return 0;
    113 }
    View Code

      建图超机智的,我想不到啊!!

    2017-02-25 10:55:41


    【今天我要用单纯形水这题】

    【趁我还记得模板怎么背】

    【---需要初始化版本】

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<ctime>
     7 using namespace std;
     8 #define Maxm 1010
     9 #define Maxn 10010 
    10 const double eps=1e-9,INF=1e15;
    11  
    12 int m,n;
    13  
    14 double a[Maxm][Maxn];
    15 // int id[Maxn*2];
    16  
    17 double myabs(double x) {return x>0?x:-x;}
    18  
    19 void Pivot(int l,int e)
    20 {
    21     // swap(id[l+n],id[e]);
    22     double t=a[l][e];a[l][e]=1;
    23     for(int j=0;j<=n;j++) a[l][j]/=t;
    24     for(int i=0;i<=m;i++) if(i!=l&&myabs(a[i][e])>eps)
    25     {
    26         t=a[i][e];a[i][e]=0;
    27         for(int j=0;j<=n;j++) a[i][j]-=a[l][j]*t;
    28     }
    29 }
    30  
    31 bool init()
    32 {
    33     while(1)
    34     {
    35         int l=0,e=0;
    36         for(int i=1;i<=m;i++) if(a[i][0]<-eps&&(!l||(rand()&1))) l=i;
    37         if(!l) break;
    38         for(int j=1;j<=n;j++) if(a[l][j]<-eps&&(!e||(rand()&1))) e=j;
    39         if(!e) return 0;
    40         Pivot(l,e);
    41     }
    42     return 1;
    43 }
    44  
    45 bool simplex()
    46 {
    47     while(1)
    48     {
    49         int l=0,e=0;double mn=INF;
    50         for(int j=1;j<=n;j++) if(a[0][j]>eps) {e=j;break;}
    51         if(!e) break;
    52         for(int i=1;i<=m;i++) if(a[i][e]>eps&&mn>a[i][0]/a[i][e])
    53             mn=a[i][0]/a[i][e],l=i;
    54         if(!l) return 0;
    55         Pivot(l,e);
    56     }
    57     return 1;
    58 }
    59  
    60 int main()
    61 {
    62     srand(2333);
    63     scanf("%d%d",&m,&n);
    64     for(int i=1;i<=m;i++) {scanf("%lf",&a[i][0]);a[i][0]=-a[i][0];}
    65     for(int i=1;i<=n;i++)
    66     {
    67         int s,t;
    68         scanf("%d%d%lf",&s,&t,&a[0][i]);a[0][i]=-a[0][i];
    69         for(int j=s;j<=t;j++) a[j][i]=-1;
    70     }
    71     if(init()&&simplex())
    72     {
    73         printf("%.0lf
    ",a[0][0]);
    74     }
    75     else printf("-1
    ");
    76     return 0;
    77 }
    View Code

    【对偶版本,不需要初始化,快10s!!!】

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<ctime>
     7 using namespace std;
     8 #define Maxm 1010
     9 #define Maxn 10010 
    10 const double eps=1e-9,INF=1e15;
    11 
    12 int m,n;
    13 
    14 double a[Maxn][Maxm];
    15 // double a[Maxm][Maxn];
    16 // int id[Maxn*2];
    17 
    18 double myabs(double x) {return x>0?x:-x;}
    19 
    20 void Pivot(int l,int e)
    21 {
    22     // swap(id[l+n],id[e]);
    23     double t=a[l][e];a[l][e]=1;
    24     for(int j=0;j<=n;j++) a[l][j]/=t;
    25     for(int i=0;i<=m;i++) if(i!=l&&myabs(a[i][e])>eps)
    26     {
    27         t=a[i][e];a[i][e]=0;
    28         for(int j=0;j<=n;j++) a[i][j]-=a[l][j]*t;
    29     }
    30 }
    31 
    32 bool init()
    33 {
    34     while(1)
    35     {
    36         int l=0,e=0;
    37         for(int i=1;i<=m;i++) if(a[i][0]<-eps&&(!l||(rand()&1))) l=i;
    38         if(!l) break;
    39         for(int j=1;j<=n;j++) if(a[l][j]<-eps&&(!e||(rand()&1))) e=j;
    40         if(!e) return 0;
    41         Pivot(l,e);
    42     }
    43     return 1;
    44 }
    45 
    46 bool simplex()
    47 {
    48     while(1)
    49     {
    50         int l=0,e=0;double mn=INF;
    51         for(int j=1;j<=n;j++) if(a[0][j]>eps) {e=j;break;}
    52         if(!e) break;
    53         for(int i=1;i<=m;i++) if(a[i][e]>eps&&mn>a[i][0]/a[i][e])
    54             mn=a[i][0]/a[i][e],l=i;
    55         if(!l) return 0;
    56         Pivot(l,e);
    57     }
    58     return 1;
    59 }
    60 
    61 int main()
    62 {
    63     srand(2333);
    64     scanf("%d%d",&m,&n);
    65     for(int i=1;i<=m;i++) {scanf("%lf",&a[0][i]);a[0][i]=a[0][i];}
    66     for(int i=1;i<=n;i++)
    67     {
    68         int s,t;
    69         scanf("%d%d%lf",&s,&t,&a[i][0]);a[i][0]=a[i][0];
    70         for(int j=s;j<=t;j++) a[i][j]=1;
    71     }
    72     swap(n,m);
    73     if(/*init()&&*/simplex())
    74     {
    75         printf("%.0lf
    ",-a[0][0]);
    76     }
    77     else printf("-1
    ");
    78     return 0;
    79 }
    View Code

    对偶就是i和j反,系数正负全反。。。

  • 相关阅读:
    2020 CCPC Wannafly Winter Camp Day2 E阔力梯的树(树上启发式合并)
    牛客练习赛73D 离别(线段树)
    从零开始部署图书管理系统
    linux下安装nginx(编译安装)及反向代理及负载均衡
    linux下MariaDB安装
    linux下virtualenvwrapper安装
    linux下安装虚拟环境
    linux下安装django2.2
    linux下安装nginx(yum源安装)
    linux系统优化命令--day03
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6441173.html
Copyright © 2020-2023  润新知