BZOJ1061: [NOI2008] Volunteer Recruitment - Problem Solving

https://www.lydsy.com/JudgeOnline/problem.php?id=1061

https://www.luogu.org/problemnew/show/P3980

After the successful bid for the Olympic Games, after unremitting efforts, Bu Bu finally became the director of the human resources department of the subsidiary company of the Olympic Organizing Committee. As soon as Bu Bu took office, he encountered a difficult problem: recruiting a group of short-term volunteers for the upcoming Olympic new project. It is estimated that this project will take N days to complete, of which at least Ai individuals are required on the i-th day. Boob learned through understanding that there are a total of M types of volunteers that can be recruited. Among them, the i-th class can work from the Si day to the Ti day, and the recruitment fee is Ci yuan per person. The new officer took office for three fires. In order to complete his work well, Boob hopes to recruit enough volunteers with as little cost as possible, but this is not his specialty! So Boob found you, hoping you could help him design an optimal recruitment plan.

(The question first said that the other data does not exceed 2^31-1, then if c=2^31-1, a=2^31-1 in this question, I am afraid it is not going to explode longlong (funny))

A very fantastic flow of mapping costs.

The initial idea was to flow the upper and lower bound fees, and then flow to the confluence point every day, and then I was very entangled in the question of whether or not to take people back, so I gave up the treatment.

Considering that the S node has INF at the beginning, we hope that there is still INF traffic to T, but when every day passes (for example, in s days), unfortunately, this edge is INF-a[i], what should I do? ? We need to pay c to send some traffic to t+1 (obviously, these people will be less needed in s~t days, which is equivalent to these people working in s~t days in disguise ).

(Of course, if the final traffic is not INF, it means there is no solution.)

...Yes, this is the idea of ​​​​constructing this question, which is very wonderful.

Thinking about it carefully, it effectively avoids the problems of the lower bound, the continuous work of personnel and the entry and withdrawal of personnel (it is really impossible to draw a perceptual picture).

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1010;
const int M=3e4+5;
const int INF=1e9;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct node{
    int nxt,to,w,b;
}edge[M];
int head[N],cnt=-1;
inline void add(int u,int v,int w,int b){
    edge[++cnt].to=v;edge[cnt].w=w;edge[cnt].b=b;
    edge[cnt].nxt=head[u];head[u]=cnt;
    edge[++cnt].to=u;edge[cnt].w=0;edge[cnt].b=-b;
    edge[cnt].nxt=head[v];head[v]=cnt;
}
int dis[N];
bool vis[N];
inline bool spfa(int s,int t,int n){
    deque<int>q;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)dis[i]=INF;
    dis[t]=0;q.push_back(t);vis[t]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop_front();vis[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            int v=edge[i].to;
            int b=edge[i].b;
            if(edge[i^1].w&&dis[v]>dis[u]-b){
                dis[v]=dis[u]-b;
                if(!vis[v]){
                    vis[v]=1;
                    if(!q.empty()&&dis[v]<dis[q.front()]){
                        q.push_front(v);
                    }else{
                        q.push_back(v);
                    }
                }
            }
        }
    }
    return dis[s]<INF;
}
int ans,cur[N];
int dfs(int u,int flow,int m){
    if(u==m){
        vis[m]=1;
        return flow;
    }
    int res=0,delta;
    vis[u]=1;
    for(int &e=cur[u];e!=-1;e=edge[e].nxt){
        int v=edge[e].to;
        int b=edge[e].b;
        if(!vis[v]&&edge[e].w&&dis[u]-b==dis[v]){
            delta=dfs(v,min(edge[e].w,flow-res),m); 
            if(delta){
                edge [e] .w - = delta;
                edge [e ^ 1 ] .w + = delta;
                res+=delta;
                   ans+=delta*b;
                if(res==flow)break;
            }
        }
    }
    return res;
}
inline int costflow(int S,int T,int n){
    int flow=0;
    while(spfa(S,T,n)){
        do{
            for(int i=1;i<=n;i++)cur[i]=head[i];
            memset(vis,0,sizeof(vis));
            flow+=dfs(S,INF,T);
        }while(vis[T]);
    }
    return ans;
}
int main(){
    memset(head,-1,sizeof(head));
    int n=read(),m=read(),S=n+2,T=S+1;
    add(S,1,INF,0);
    for(int i=1;i<=n;i++){
        add(i,i+1,INF-read(),0);
    }
    add(n+1,T,INF,0);
    for(int i=1;i<=m;i++){
        int s=read(),t=read(),c=read();
        add(s,t+1,INF,c);
    }
    printf("%d\n",costflow(S,T,T));
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 + Author of this article: luyouqi233. +

 +Welcome to my blog: http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325382498&siteId=291194637