• [NOI2008]志愿者招募


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

    有n天,每天都需要一定数量的人。有m种志愿者,第i个志愿者可以在si到ti天工作,但需要费用ci,求最小费用。

    有上下界无源汇费用流。

    开一个超级S,超级T,然后每个点计算一下入度与出度之差,f[i]=in[i]-out[i] 

    如果>0 向S连一条流量f[i],费用为0的边。

    如果<0 向T连一条流量-f[i],费用为0的边。

    这道题中,对每一个志愿者,从si向ti+1的点连费用为ci,流量INF的边。

    然后每一个点向前一个点连流量INF,费用为0的边。

    然后跑一遍费用流~

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define S 0
    #define T 1002
    #define MAXN 1005
    #define MAXL 10000
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int  x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int n,m,cnt=1,ans=0;
    int head[MAXN+5];
    int in[MAXN+5];
    int out[MAXN+5];
    int d[MAXN+5];
    bool mark[MAXN+5];
    queue<int> q;
    
    struct edge{
        int to,next,w,c;
    }e[MAXL*5];
    
    void ins(int f,int t,int w,int c)
    {
        e[++cnt].next=head[f];
        head[f]=cnt;
        e[cnt].to=t;
        e[cnt].w=w;
        e[cnt].c=c;
    }
    
    int dfs(int x,int f)
    {
        int used=0;mark[x]=1;
        if(x==T) return f;
        for(int i=head[x];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!mark[v]&&d[v]==d[x]-e[i].c&&e[i].w)
            {
                int w=dfs(v,min(f-used,e[i].w));
                ans+=w*e[i].c;
                e[i].w-=w;
                e[i^1].w+=w;
                used+=w;
                if(used==f) return f;
            }
        }
        return used;
    }
    
    bool bfs()
    {
        q.push(T);
        for(int i=0;i<T;i++) d[i]=INF;
        memset(mark,0,sizeof(mark));
        d[T]=0;mark[T]=1;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if(d[u]+e[i^1].c<d[v]&&e[i^1].w)
                {
                    d[v]=d[u]+e[i^1].c;
                    if(!mark[v])
                    {
                        mark[v]=1;q.push(v);
                    }
                }
            }
            mark[u]=0;
        }
        return d[S]!=INF;
    }
    
    inline void insw(int f,int t,int w,int c)
    {
        ins(f,t,w,c);ins(t,f,0,-c);
    }
    
    int main()
    {
        n=read();m=read();int pre=0;
        for(int i=1;i<=n;i++)
        {
            int x=read();
            if(x>pre) insw(S,i,x-pre,0);
            if(x<pre) insw(i,T,pre-x,0);
            pre=x;
            insw(i+1,i,INF,0);
        }
        insw(n+1,T,pre,0);
        for(int i=1;i<=m;++i)
        {
            int x=read(),y=read(),c=read();
            insw(x,y+1,INF,c);
        }
        while(bfs())
        {
            mark[T]=1;
            while(mark[T])
            {
                memset(mark,0,sizeof(mark));
                dfs(S,INF);
            }
        }
        cout<<ans;
        return 0;
    }
    FallDream代表秋之国向您问好! 欢迎您来我的博客www.cnblogs.com/FallDream
  • 相关阅读:
    MongoDB的索引(六)
    DMZ原理与应用
    MongoDB的增、删、改、查操作(五)
    一分钟了解mongodb(转)
    mongodb-java-driver基本用法
    Mongodb相对于关系型数据库的优缺点(转)
    什么场景应该用 MongoDB(转)
    MongoDB使用场景和局限 (转)
    matlab7与win7不兼容
    sublime的使用
  • 原文地址:https://www.cnblogs.com/FallDream/p/noi2008T3.html
Copyright © 2020-2023  润新知