您的位置:首页 > 其它

bzoj1061 [Noi2008]志愿者招募 单纯形(模板)

2017-06-21 21:27 295 查看
题目大意:

有n天,m种志愿者。

每天需要ai个志愿者,雇佣每种志愿者的费用为ci,每个志愿者可以在Si天到Ti天工作。

问最小花费。

题目分析:

题解PoPoQQQ.html

单纯形wyfcyx.pdf

据说这道题网络流神题,单纯形裸题

首先我们根据题意

设第i天需要xi个志愿者。

Ai,j代表第j个人可以在第i天工作。

bi代表第i天需要的人数。

ci代表租用第i类志愿者需要的花费。

∑Ai,jxj≥bi

Minisize∑mici∗xi

这个不是单纯形的标准形式,对偶原理搞一波就变成了

∑ATi,j∗yj≤ci

Maxisize∑nibi∗yi

这样就变成了单纯形裸题QWQ

(向Po姐学习!!!)

代码如下:

#include <cstdio>
#include <cmath>
#define N 1010
#define M 10100
using namespace std;
const double INF=1e10;
const double eps=1e-7;
int n,m;
double A[M]
,b[M],c
,v;
void Pivot(int l,int e)
{
b[l]/=A[l][e];
for(int i=1;i<=n;i++)
if(i!=e)
A[l][i]/=A[l][e];
A[l][e]=1/A[l][e];
for(int i=1;i<=m;i++)
if(i!=l && fabs(A[i][e])>eps)
{
b[i]-=A[i][e]*b[l];
for(int j=1;j<=n;j++)
if(j!=e)
A[i][j]-=A[i][e]*A[l][j];
A[i][e]=-A[i][e]*A[l][e];
}

v+=c[e]*b[l];
for(int i=1;i<=n;i++)
if(i!=e)
c[i]-=c[e]*A[l][i];
c[e]=-c[e]*A[l][e];
}
double Simplex()
{
int i,l,e;
while(true)
{
for(i=1;i<=n;i++)
if(c[i]>eps) break;
if((e=i)==n+1) return v;
double tmp=INF;
for(i=1;i<=m;i++)
if(A[i][e]>eps && b[i]/A[i][e]<tmp)
tmp=b[i]/A[i][e],l=i;
if(tmp==INF) return INF;
Pivot(l,e);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lf",&c[i]);
for(int i=1,x,y;i<=m;i++)
{
scanf("%d%d%lf",&x,&y,&b[i]);
for(int j=x;j<=y;j++)
A[i][j]=1;
}
double ans=Simplex();
printf("%d\n",int(ans+0.5));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: