【bzoj1061】[Noi2008]志願者招募

= =跟上一道基本相同,可以單純形法解線性規劃,也可以費用流.
寫費用流的話建圖就是一般的線性規劃轉費用流的套路,加上基變量,然後化成等式,每個下式減上式之後可以化成表示流量平衡的等式,然後根據等式建圖就好了,跑一個最小費用最大流.
寫單純形沒有寫網絡流好理解,單純形的話因爲這是最小化費用的,首先要轉化成對偶問題(我到現在也不能理解對偶問題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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章