bzoj 1061: [Noi2008]志愿者招募

Posted Soda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1061: [Noi2008]志愿者招募相关的知识,希望对你有一定的参考价值。

/*
    题目大意:
        项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者 
    题解:
        http://blog.csdn.net/lych_cys/article/details/50703729 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 1e9
#define maxn 10010
using namespace std;
int n,m,head[maxn],num=1,a[maxn],S,T,ans,dis[maxn];
bool mark[maxn],vis[maxn];
struct node{int to,pre,c,cc;}e[maxn*10];
void Insert(int from,int to,int c,int cc){
    e[++num].to=to;
    e[num].c=c;
    e[num].cc=cc;
    e[num].pre=head[from];
    head[from]=num;
}
bool spfa(){
    queue<int>q;
    q.push(T);
    for(int i=S;i<=T;i++)vis[i]=0,dis[i]=INF;
    vis[T]=1;dis[T]=0;
    while(!q.empty()){
        int now=q.front();q.pop();vis[now]=0;
        for(int i=head[now];i;i=e[i].pre){
            int to=e[i].to;
            if(dis[to]>dis[now]-e[i].cc&&e[i^1].c){
                dis[to]=dis[now]-e[i].cc;  
                if(!vis[to])vis[to]=1,q.push(to);
            }
        }
    }
    return dis[S]!=INF;
}
int dfs(int now,int flow){
    mark[now]=1;
    if(now==T)return flow;
    int delta,used=0;
    for(int i=head[now];i;i=e[i].pre){
        int to=e[i].to;
        if(e[i].c&&!mark[to]&&dis[to]==dis[now]-e[i].cc){
            delta=dfs(to,min(flow-used,e[i].c));
            ans+=delta*e[i].cc;
            used+=delta;
            e[i].c-=delta;e[i^1].c+=delta;
            if(used==flow)return used;
        }
    }
    return used;
}
void solve(){
    int tmp=0;
    while(spfa()){
        mark[T]=1;
        while(mark[T]){
            memset(mark,0,sizeof(mark));
            tmp+=dfs(S,INF);
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    S=0,T=1005;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        int cha=a[i]-a[i-1];
        if(cha>0)Insert(S,i,cha,0),Insert(i,S,0,0);
        else Insert(i,T,-cha,0),Insert(T,i,0,0);
        Insert(i+1,i,INF,0),Insert(i,i+1,0,0);
    }
    Insert(n+1,T,a[n],0);Insert(T,n+1,0,0);
    int l,r,C;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&l,&r,&C);
        Insert(l,r+1,INF,C);Insert(r+1,l,0,-C);
    }
    solve();
    printf("%d",ans);
    return 0;
} 

 

以上是关于bzoj 1061: [Noi2008]志愿者招募的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]

bzoj1061: [Noi2008]志愿者招募

bzoj 1061: [Noi2008]志愿者招募

BZOJ1061:[NOI2008]志愿者招募——题解

bzoj 1061 [Noi2008]志愿者招募(数学模型,MCMF)

bzoj1061 [Noi2008]志愿者招募