Hdu 3572 Task Schedule [最大流] 任务分配,判断满流

来源:互联网 发布:有没有类似知乎的网站 编辑:程序博客网 时间:2024/05/16 22:51

题目意思:

给出 N 件任务和 M台机器, 这N件任务都一个限制: 必须在 [S,E] 之间完成, 而且完成的时间不能超过 P.

一台机器每天只能做意见任务, 不过庆幸的是: 任务是可以拆分的, 比如一件任务要3天完成, 那么你就可以将呀拆分

成3份. 现在问: 在所有机器慢负荷运转的情况下, 如何分配这些任务使得在最后的期限时, 所有任务都能完成.

解题 :

仔细分析下题目不难想到是个网络流模型, 问题就是求源点的流是否能够全部流到汇点. 关键在于构图. 我们选取一个

超级源点和一个超级汇点, 一开始把源点指向所有的任务, 边权就是完成这件任务需要的天数, 然后按照完成这件任务

的时间区间, 将任务分成 E-S+1份, 意思就是在这几天中每天都可以完成这件任务的一份.这样, 就可以在任务和能够完

成它的这些天之间连边, 边权为1, 因为每次只能做一份, 最后在所有的天和汇点之间连边, 边权为M, 表示每一天, M台

机器可以完成M份工作:

 

#include<iostream>#include<cmath>#include<cstring> using namespace std;   #define MAXN 500 #define MAXE 500002 #define INF 0x7ffffff      int ne,nv,tmp,s,t,index;  struct Edge{     int next,pair;     int v,cap,fLow; }edge[MAXE];int net[MAXN];int maxday; int ISAP() { int numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];      int cur_fLow,max_fLow,u,tmp,neck,i;     memset(dist,0,sizeof(dist));     memset(numb,0,sizeof(numb));     memset(pre,-1,sizeof(pre));     for(i = 1 ; i <= nv ; ++i)         curedge[i] = net[i];     numb[nv] = nv;     max_fLow = 0;     u = s;     while(dist[s] < nv)     {         if(u == t)         {             cur_fLow = INF;             for(i = s; i != t;i = edge[curedge[i]].v)              {                   if(cur_fLow > edge[curedge[i]].cap)                 {                     neck = i;                     cur_fLow = edge[curedge[i]].cap;                 }             }             for(i = s; i != t; i = edge[curedge[i]].v)             {                 tmp = curedge[i];                 edge[tmp].cap -= cur_fLow;                 edge[tmp].fLow += cur_fLow;                 tmp = edge[tmp].pair;                 edge[tmp].cap += cur_fLow;                 edge[tmp].fLow -= cur_fLow;             }             max_fLow += cur_fLow;             u = neck;         }         /* if .... eLse ... */        for(i = curedge[u]; i != -1; i = edge[i].next)             if(edge[i].cap > 0 && dist[u] == dist[edge[i].v]+1)                 break;         if(i != -1)         {             curedge[u] = i;             pre[edge[i].v] = u;             u = edge[i].v;         }else{             if(0 == --numb[dist[u]]) break;             curedge[u] = net[u];             for(tmp = nv,i = net[u]; i != -1; i = edge[i].next)                 if(edge[i].cap > 0)                     tmp = tmp<dist[edge[i].v]?tmp:dist[edge[i].v];             dist[u] = tmp + 1;             ++numb[dist[u]];             if(u != s) u = pre[u];         }     }          return max_fLow; }void addedge(int u,int v,int f){edge[index].next = net[u];     edge[index].v = v;     edge[index].cap = f;     edge[index].fLow = 0;     edge[index].pair = index+1;     net[u] = index++;     edge[index].next = net[v];     edge[index].v = u;     edge[index].cap = 0;     edge[index].fLow = 0;     edge[index].pair = index-1;     net[v] = index++;} int main() {     int i,j,np,nc,m,n;     int a,b,d,k,vaL;int tt;scanf("%d",&tt);for(int cas=1;cas<=tt;++cas){ int cases=1;int maxval=0;maxday=0;scanf("%d%d",&n,&m);  index=0;//index从0开始扫         s = 0;         t = 0;          memset(net,-1,sizeof(net));        for(i=1;i<=n;i++){int pi,si,ei;scanf("%d%d%d",&pi,&si,&ei);maxday=max(maxday,ei);maxval+=pi;addedge(s,i,pi);for(j=si;j<=ei;j++)addedge(i,n+j,1); }t=n+maxday+1;nv=t+1;for(i=1;i<=maxday;i++)addedge(i+n,t,m);int ans=ISAP();if (ans == maxval)              printf("Case %d: Yes\n\n", cas);          else printf("Case %d: No\n\n", cas);      }     return 0; }