Hdu 3572Task Schedule

题意:

有M个机器,有N个任务。每个任务必须在Si 或者以后开始做,在Ei 或者之前完成,完成任务必须处理Pi 个时间单位。其中,每个任务可以在任意(空闲)机器上工作,每个机器的同一时刻只能工作一个任务,每个任务在同一时刻只能被一个机器工作,而且任务做到一半可以打断,拿去其他机器做。问:能否在规定时间内把任务做完。

源点与每个任务都连一条边,容量为要求的天数p,然后每个任务都与相应的时间点连边,边容量为1,每个时间点与汇点之间连边,边容量为m,为机器数(表示每个时间点最多可以有m台机器处理任务),判断满流即可

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define For(i,j,k) for(int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(int i=(j);i>=(int)k;i--)
#define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
#define Set(a,b) memset(a,b,sizeof(a))
const int N=1001,M=100001,INF=0x3f3f3f3f;
using namespace std;
template <class T> inline void read(T &x){
    x=0;char c=getchar();int f(0);
    while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    x=f?-x:x;
}
template <class T>inline void chkmin(T &a,T b){a=a>b?b:a;}
template <class T>inline void chkmax(T &a,T b){a=a<b?b:a;}

int Begin[N],to[M<<1],Next[M<<1],f[M<<1],e=1,n,m;
inline void add(int x,int y,int z){
    to[++e]=y,Next[e]=Begin[x],Begin[x]=e,f[e]=z;
}
struct isap{
    int s,t,gap[N],d[N],p[N],cur[N];
    #define Retr(u) for(u=t;u^s;u=to[p[u]^1])
    inline void init(){
        queue<int>q;
        For(i,0,t)d[i]=INF,cur[i]=Begin[i],gap[i]=0;
        d[t]=0;gap[0]=1;
        q.push(t);
        while(!q.empty()){
            int r=q.front();q.pop();
            Rep(i,r)
                if(f[i^1]&&d[v]>d[r]+1)
                    ++gap[d[v]=d[r]+1],q.push(v);
        }
    }
    inline int Augment(){
        int u,a=INF;
        Retr(u)chkmin(a,f[p[u]]);
        Retr(u)f[p[u]]-=a,f[p[u]^1]+=a;
        return a;
    }
    inline int Maxflow(int _s,int _t){
        int i,u=s=_s,flow=0;t=_t;
        init();
        while(d[s]<t){
            if(u==t)flow+=Augment(),u=s;
            for(i=cur[u];i;i=Next[i])
                if(f[i]&&d[to[i]]+1==d[u])break;
            if(!i){
                if(--gap[d[u]]==0)break;
                d[u]=n;cur[u]=Begin[u];
                Rep(i,u)
                    if(f[i])chkmin(d[u],d[v]+1);
                ++gap[d[u]];
                if(u!=s)u=to[p[u]^1];
            }else cur[u]=i,p[u=to[i]]=i;
        }
        return flow;
    }
}F;
int P[N],S[N],E[N],s_,t_,sum;
inline void work(){
    Set(Begin,0),e=1,s_=sum=0;
    read(n),read(m);
    For(i,1,n){
        read(P[i]),read(S[i]),read(E[i]);
        sum+=P[i];
        chkmax(s_,E[i]);
    }
    s_+=n+1;t_=s_+1;
    For(i,1,n){
        add(s_,i,P[i]),add(i,s_,0);
        For(j,S[i],E[i])
            add(i,j+n,1),add(j+n,i,0);
    }
    For(i,1+n,s_-1)
        add(i,t_,m),add(t_,i,0);
}
int main(){
    int T;
    read(T);
    For(i,1,T){
        work();
        printf("Case %d: %s\n",i,F.Maxflow(s_,t_)==sum?"Yes":"No");
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值