【bzoj1061】[Noi2008]志願者招募
阿新 • • 發佈:2019-02-06
= =跟上一道基本相同,可以單純形法解線性規劃,也可以費用流.
寫費用流的話建圖就是一般的線性規劃轉費用流的套路,加上基變數,然後化成等式,每個下式減上式之後可以化成表示流量平衡的等式,然後根據等式建圖就好了,跑一個最小費用最大流.
寫單純形沒有寫網路流好理解,單純形的話因為這是最小化費用的,首先要轉化成對偶問題(我到現在也不能理解對偶問題QAQ),我的理解就是把原本的B[i]寫成c[i],c[i]寫成B[i],n寫成m,m寫成n,然後xjb搞一搞就好了,而且本來也感覺單純形這個模板憑理解很難打= =,其實背的話更難,因為背模板其實都是建立在理解的基礎之上的,其實就是寫的熟練罷了,不理解的話真的特別容易寫錯,跟自適應辛普森積分一樣(捂臉),mdzz好的我承認我是數學不好.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e3+5,M=1e4+5;
const double eps=1e-7,inf=1e10;
double ans,A[M][N],B[M],c[N];
int n,m,L,R;
inline 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;i<=m;++i)
if (i!=l&&fabs(A[i][e])>eps)
{
B[i]-=B[l]*A[i][e];
for (int j=1;j<=n;j++)
if (j!=e)A[i][j]-=A[i][e]*A[l][j];
A[i][e]=-A[l][e]*A[i][e];
}
ans+=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];
}
inline void simplex()
{
int e;
while(1)
{
for (e=1;e<=n;e++)
if (c[e]>eps)break;
if (e==n+1) break;
double t,delta=inf;int l;
for (int i=1;i<=m;++i)
if (A[i][e]>eps&&(t=B[i]/A[i][e])<delta)
l=i,delta=t;
pivot(l,e);
}
}
int main()
{
cin>>n>>m;
for (int i=1;i<=n;++i)
scanf("%lf",&c[i]);
for (int i=1;i<=m;++i)
{
scanf("%d%d%lf",&L,&R,&B[i]);
for (int j=L;j<=R;++j)
A[i][j]=1;
}
simplex();
printf("%.0lf",ans);
}