[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 }