• 【网络流】【BZOJ1061】【NOI2008】志愿者招募


    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1061

    题意:问你如何购买志愿者使得满足题意的总费用最小。

    解题思路:首先,由于志愿者存在的时间是一个区间,我们考虑使用差分序列,这样的话我们就可以比较轻松的建图跑一遍最小费用最大流了。我们定义每个中间点代表着每一天,显然第i天需要的志愿者是i-1天的志愿者+x,用差分即可完成。建图方式详见AC代码。

    附:AC代码(因为我比较蒻,所以打了low的一逼的SPFAcostflow,所以跑的巨慢。)

    #include<stdio.h>
    #include<string.h>
    #define S 0
    #define T 1002
    #define MAXN 1005
    #define inf 0x7fffffff
    #define min(a,b) (a<b?a:b)
    struct zxy{int to,next,v,c;}edge[35000];
    int n,m,cnt=1,head[MAXN],dis[MAXN],pre[MAXN],que[MAXN];
    bool vis[MAXN];
    inline void ins(int x,int y,int v,int l){
        edge[++cnt].to=y,edge[cnt].c=l,edge[cnt].v=v,edge[cnt].next=head[x],head[x]=cnt;
    }
    inline void insw(int x,int y,int v,int l){ins(x,y,v,l); ins(y,x,0,(-1)*l);}
    inline int in(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    inline bool SPFA_costflow(int s,int e){
        register int h=0,t=1,w,v;
        memset(dis,127/3,sizeof(dis));
        dis[s]=0,vis[s]=1,que[1]=s;
        while(h!=t){
            (++h)%=MAXN;
            w=que[h];
            for (register int i=head[w]; i; i=edge[i].next){
                v=edge[i].to;
                if (dis[v]>dis[w]+edge[i].c&&edge[i].v){
                    dis[v]=dis[w]+edge[i].c;pre[v]=i;
                    if (!vis[v]){
                        vis[v]=1;
                        if (dis[v]<dis[que[h+1]]){
                            que[h]=v;h=(h-1+MAXN)%MAXN;
                        }
                        else{
                            (++t)%=MAXN;que[t]=v;   
                        }
                    }
                }
            }
            vis[w]=0;
        }
        return dis[e]!=dis[MAXN-1];
    }
    int costflow(int s,int t){
        int cost=0;
        while(SPFA_costflow(s,t)){
            int mi=inf;
            for (register int i=t; i; i=edge[pre[i]^1].to)
                mi=min(mi,edge[pre[i]].v);
            for (register int i=t; i; i=edge[pre[i]^1].to)
                edge[pre[i]].v-=mi,edge[pre[i]^1].v+=mi;
            cost+=mi*dis[t];
        }
        return cost;
    }
    void init(){
        n=in(),m=in();int x=0,pre=0;
        for (int i=1; i<=n; ++i){
            register int t=in(); x=t-pre;pre=t;
            if (x>0) insw(S,i,x,0);
            else insw(i,T,(-1)*x,0);
            insw(i+1,i,inf,0);
        }
        insw(n+1,T,inf,0);
        for (register int i=1; i<=m; ++i){
            register int l=in(),r=in(),v=in();
            insw(l,r+1,inf,v);
        }
    }
    int main(){
        init();
        printf("%d",costflow(S,T));
    }
  • 相关阅读:
    Android 使用MediaPlayer 播放 视频
    Android加载asset的db
    MAC SVN 基本设置 终端命令
    AFNetWork 简单实用demo
    IntelliJ IDEA导出Java 可执行Jar包
    Xcode快速排错
    Listview多tab上滑悬浮
    N最短路径分词
    进程监控工具supervisor
    nginx配置指南
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ1061.html
Copyright © 2020-2023  润新知