[NOI2008]志愿者招募

题目:洛谷P3980。

题目大意:
有n天,每天需要至少\(a_i\)个人。现在有m种人,每种人可以在第\(s_i\)到第\(t_i\)天工作,花费\(c_i\)的价值。
问至少花费多少价值才能满足需要(保证一定有解)。
解题思路:
网络流。把每天当做一个节点,向下一个节点连容量INF-\(a_i\),费用0的边。
然后对于每个人,从\(s_i\)向\(t_i +1\)连容量为INF,费用为\(c_i\)的边。
最后从1到n+1跑费用流,费用即答案。
主要思路就是把需要的人数挖掉,然后让志愿者填满剩下的容量。

C++ Code:

#include<bits/stdc++.h>
#define S 0
#define N 1007
#define inf 0x3f3f3f
inline int readint(){
    int c=getchar(),d=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
    d=(d<<3)+(d<<1)+(c^'0');
    return d;
}
int n,m,T,head[N],cnt=1,dis[N],pre_e[N],a[N];
bool vis[N];
int q[300002];
struct edge{
    int from,to,cap,cost,nxt;
}e[N<<5];
inline void addedge(const int from,const int to,const int cap,const int cost){
    e[++cnt]=(edge){from,to,cap,cost,head[from]};
    head[from]=cnt;
    e[++cnt]=(edge){to,from,0,-cost,head[to]};
    head[to]=cnt;
}
bool spfa(int& flow,int& cost){
    memset(dis,0x3f,sizeof dis);
    memset(pre_e,0,sizeof pre_e);
    memset(a,0x3f,sizeof a);
    memset(vis,0,sizeof vis);
    dis[S]=0;
    vis[S]=1;
    q[1]=S;
    int l=0,r=1;
    while(l!=r){
    	int u=q[l=l%300000+1];
    	vis[u]=0;
    	for(int i=head[u];i!=-1;i=e[i].nxt)
        if(e[i].cap&&dis[e[i].to]>dis[u]+e[i].cost){
            dis[e[i].to]=dis[u]+e[i].cost;
            a[e[i].to]=std::min(e[i].cap,a[u]);
            pre_e[e[i].to]=i;
            if(!vis[e[i].to]){
                vis[e[i].to]=1;
                q[r=r%300000+1]=e[i].to;
            }
        }
    }
    if(dis[T]==0x3f3f3f3f)return 0;
    flow+=a[T];
    cost+=dis[T]*a[T];
    for(int i=T;i!=S;i=e[pre_e[i]].from){
        e[pre_e[i]].cap-=a[T];
        e[pre_e[i]^1].cap+=a[T];
    }
    return 1;
}
int main(){
    T=(n=readint())+2,m=readint();
    memset(head,-1,sizeof head);
    addedge(S,1,inf,0);
    addedge(n+1,T,inf,0);
    for(int i=1;i<=n;++i)addedge(i,i+1,inf-readint(),0);
    for(int i=1;i<=m;++i){
        int s=readint(),t=readint(),C=readint();
        addedge(s,t+1,inf,C);
    }
    int flow=0,cost=0;
    while(spfa(flow,cost));
    printf("%d\n",cost);
    return 0; 
}

猜你喜欢

转载自www.cnblogs.com/Mrsrz/p/9105364.html