[bzoj1061]志愿者招募

费用流裸题。。不过我不会建图。。据说那个年代没有人写费用流

设第i天选第i类人xi个,每种人的费用是ci,第i天需要bi个人,aij为1表示某个人可以从第i天干到第j天,显而易见可以构造出线性不等式组了。

Minimize: CX

  s.t.   AX>=B

          X>=0

然而我们发现这是一个目标函数为最小化的线性规划,显然不可以直接用单纯形算法搞,所以要用到一种叫做对偶性的性质(具体算法导论里有貌似),即该线性不等式组的目标值同等于下面这个线性不等式组。

Maximize: BX

  s.t.   AX<=C

          X>=0

 然后这就可以套模板了。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <cstring>
 6 using namespace std;
 7  
 8 int n,m;
 9 double a[10010][1010];
10 int get(){for(int i=1;i<=n;i++)if(a[0][i]>0)return i;return 0;}
11 int main(){
12     scanf("%d%d",&n,&m);
13     for(int i=1;i<=n;i++){
14         scanf("%lf",&a[0][i]);
15     }
16     for(int i=1,s,t;i<=m;i++){
17         scanf("%d%d%lf",&s,&t,&a[i][0]);
18         for(int j=s;j<=t;j++)a[i][j]=1;
19     }
20     while(int t=get()){
21         double min=0x3f3f3f3f;
22         int chs;
23         for(int i=1;i<=m;i++){
24             if(a[i][t]>0&&a[i][0]/a[i][t]<min){
25                 min=a[i][0]/a[i][t];
26                 chs=i;
27             }
28         }
29         if(min==0x3f3f3f3f){a[0][0]=0x3f3f3f3f;break;}
30         double x=a[chs][t],tmp;
31         for(int i=0;i<=n;i++){
32             if(i==t)a[chs][i]/=x;
33             a[chs][i]/=x;
34         }
35         for(int i=0;i<=m;i++){
36             if(i==chs||a[i][t]==0)continue;
37             if(i==0)a[i][0]+=a[chs][0]*a[i][t];
38             else a[i][0]-=a[chs][0]*a[i][t];
39             tmp=a[i][t];
40             for(int j=1;j<=n;j++){
41                 if(j==t)a[i][j]=-tmp*a[chs][t];
42                 else a[i][j]-=tmp*a[chs][j];
43             }
44         }
45     }
46     printf("%.0lf\n",a[0][0]);
47 }
View Code

 

posted @ 2017-01-08 18:02  KingSann  阅读(128)  评论(0)    收藏  举报