zoukankan      html  css  js  c++  java
  • [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
    ",cost);
        return 0; 
    }
    
  • 相关阅读:
    20165225《Java程序设计》第六周学习总结
    实验一 Java开发环境的熟悉
    20165225《Java程序设计》第五周学习总结
    移动web——bootstrap响应式工具
    移动web——bootstrap栅格系统
    移动web——bootstrap模板
    移动web——媒体查询
    移动web——轮播图
    移动web——touch事件应用
    移动web——touch事件介绍
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9105364.html
Copyright © 2011-2022 走看看