HDU 3572

来源:互联网 发布:朗道 知乎 编辑:程序博客网 时间:2024/05/18 01:49

题意:给你M台机器,N个任务,每台机器每天只能做一个任务。每个任务的最早开始时间为第SI天,需要做Pi天,允许不持续做,可以分成几次完成,但必须在第Ei天前结束(包括Ei)。

(N<=500), (M<=200) , (1<=Pi, Si, Ei<=500)

注意每个case以后要输出一个空行。


【最大流】注意到天数的范围,才500,所以可以将天数也当成点考虑进去。

建图:

源点到每个任务之间建一条边,流量为Pi,即完成该任务所需要的天数;

每个任务允许作业时间从第Si天到第Ei天,则任务点到这些天数点之间连一条边,流量为1,表示每天只能做该任务一次;

由于每天最多只能M台机器工作,所以每个表示天数的点到汇点建一条边,流量为M;


然后就是求最大流,如果最大流跟 ∑ Pi (1<=i<=n)一致就是Yes,否则No。

以下为dinic代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int maxn = 2000+10;const int maxe = 300000+10;int e,first[maxn],nxt[maxe],vv[maxe],cap[maxe];int dis[maxn],cur[maxn];        //cur数组是用来优化dfs搜索的void add_edge(int u,int v,int c){    vv[e]=v; cap[e]=c; nxt[e]=first[u]; first[u]=e++;    vv[e]=u; cap[e]=0; nxt[e]=first[v]; first[v]=e++;}bool bfs(int s,int t)           //BFS处理分层{    memset(dis,-1,sizeof dis);    queue<int> q;    dis[s]=0;    q.push(s);    while (!q.empty())    {        int u = q.front();q.pop();        for (int i=first[u];i!=-1;i=nxt[i])        {            int v = vv[i];            if (dis[v]==-1 && cap[i] > 0)            {                dis[v]=dis[u]+1;                q.push(v);            }        }    }    return dis[t]!=-1;}int dfs(int u,int t,int a)                  //dfs求增广{    if (u==t || a==0)    {return a;}    int flow=0,f;    for (int &i=cur[u];i!=-1;i=nxt[i])      //i是引用,搜索过的边,下次无需再搜    {        int v = vv[i];        if (dis[u]+1==dis[v] && ((f = dfs(v,t,min(a,cap[i])))>0))        {            cap[i]-=f;            cap[i^1]+=f;            flow+=f;            a-=f;            if (!a) {break;}        }    }    return flow;}int solve(int s,int t){    int maxflow = 0;    while(bfs(s,t))    {        for (int i=1;i<=t;i++){cur[i]=first[i];}        maxflow+=dfs(s,t,0x3f3f3f3f);    }    return maxflow;}int main (){    int T,n,m,maxflow;    scanf("%d",&T);    for (int cas = 1;cas <= T;cas++)    {        scanf("%d%d",&n,&m);        memset(first,-1,sizeof first);        e=maxflow=0;        int pi,si,ei,maxd=0,edp;        for (int i=1;i<=n;i++)        {            scanf("%d%d%d",&pi,&si,&ei);            maxflow+=pi;            add_edge(1,1+i,pi);            maxd = max(maxd,ei);            for (int j=si;j<=ei;j++)            {add_edge(i+1,n+1+j,1);}        }        edp = n+1+maxd+1;        for (int i=1;i<=maxd;i++)        {add_edge(n+1+i,edp,m);}        //点1是源点,点edp是汇点,任务点是2~n+1,天数点从n+1~maxd        if (maxflow==solve(1,edp))        {printf("Case %d: Yes\n\n",cas);}        else{printf("Case %d: No\n\n",cas);}    }    return 0;}


0 0
原创粉丝点击