hdu 3572 : Task Schedule (网络流)

题目链接

题意:

有M个机器,N个任务

对第i个任务,需要在[Si,Ei]这段时间内恰有Pi天被process

每天最多有M个机器同时工作

每一天,一个任务若被process,那么它恰占用一个机器。

 

题解:建图,设一个超级源点S编号为0,超级汇点T编号为1001,编号[1,500]表示任务[1,500],编号[501,100]表示时间[1,500] (为与原题对应,建边时用500作为偏移量)。

每一天最多同时加工M个任务,故每一天向超级汇点连一条容量为M的边 以满足此不等关系。

每个任务最多需要Pi天,那么超级汇点向每个任务连一条容量为Pi的边。

每个任务要在[Si,Ei]中选时间进行process,那么,从任务i向[Si,Ei]中的每一天都分别连一条容量为1的边。

最后,如果跑得的最大流==sigma(Pi),那么就是"Yes"了

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

namespace FastIO
{
    const static int MX=1e6;
    bool IOerror=0;
    char nc()
    {
        static char buf[MX],*p1=buf+MX,*pend=buf+MX;
        if(p1==pend)
        {
            p1=buf;
            pend=buf+fread(buf,1,MX,stdin);
            if(pend==p1)
            {
                IOerror=1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch)
    {
        return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
    }
    inline int read(int& x)
    {
        char ch;
        while(blank(ch=nc()));
        if(IOerror) return 0;
        for(x=ch-'0'; (ch=nc())>='0'&&ch<='9'; x=x*10+ch-'0'); //printf("%d===\n",x);
        return 1;
    }
}
using namespace FastIO;

const int N=1005;
const int M=1000006;
const int INF=0x3f3f3f3f;

struct Edge
{
    int to,next;
    int flow,cap;    //根据情况设定变量类型 
    Edge(){}
    Edge(int _to,int _next,int _cap,int _flow)
    {
        to=_to,next=_next,cap=_cap,flow=_flow;
    }
};
Edge edge[M<<1];
int head[N],tot;
int cur[N];
int d[N];

void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}
inline void addedge(int u,int v,int cap)
{
    edge[tot]=Edge(v,head[u],cap,0);
    head[u]=tot++;
    edge[tot]=Edge(u,head[v],0,0);
    head[v]=tot++;
}
int bfs(int s,int t)
{
    memset(d,-1,sizeof(d));
    queue<int> Q;
    Q.push(s),d[s]=0;
    while(!Q.empty())
    {
        int u=Q.front();Q.pop();
        for(int i=head[u];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(d[v]==-1&&edge[i].cap>edge[i].flow)
            {
                d[v]=d[u]+1;
                if(v==t) return 1;
                Q.push(v);
            }
        }
    }
    return ~d[t];
}
int dfs(int s,int t,int a)
{
    if(s==t||a==0) return a;
    int flow=0,df;
//    for(int& i=cur[s];~i;i=edge[i].next)
    for(int i=head[s];~i;i=edge[i].next)
    {
        int v=edge[i].to;
//        if(d[v]==d[s]+1 && 
//            (df=dfs(v,t,min(a,edge[i].cap-edge[i].flow))>0))    //这种写法 hdu6214 TLE 
        if(d[v]==d[s]+1&&edge[i].cap>edge[i].flow
            &&(df=dfs(v,t,min(a,edge[i].cap-edge[i].flow)))>0)
        {
            edge[i].flow+=df;
            edge[i^1].flow-=df;
            flow+=df;
            a-=df;
            if(a==0) break;
        }
    }
    if(flow==0) d[s]=-1;
    return flow;
}
int dinic(int s,int t)
{
    int ret=0;
    while(bfs(s,t))
    {
//        memcpy(cur,head,sizeof(cur));
        ret+=dfs(s,t,INF);
    }
    return ret;
}

int main()
{
    int T,kase=0;
    int s=0,t=1001;
    read(T);
    while(T--)
    {
        int n,m;    // n表示任务总数,m表示点容量
        int sum=0;    // sum表示实际所需总时间
        read(n),read(m);
        init();
        
        for(int i=1; i<=n; i++)
        {
            int l,p,r;
            read(p),read(l),read(r);
            sum+=p;
            addedge(s,i,p);
            for(int j=l; j<=r; j++)
                addedge(i,j+500,1);
        }
        for(int j=1; j<=500; j++)
            addedge(j+500,t,m);

        printf("Case %d: ",++kase);
        if(dinic(s,t)==sum)
            puts("Yes");
        else    puts("No");
        puts("");
    }
}

 

posted @ 2017-09-22 15:25 wy_2016 阅读(...) 评论(...) 编辑 收藏