HDU 3572 最大流

来源:互联网 发布:无差别杀人 知乎 编辑:程序博客网 时间:2024/05/16 06:36

最近在刷题和各种事情,忘记更新了,最近会把做的题目都更新出来


Task Schedule

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6018    Accepted Submission(s): 1927


Problem Description
Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened factory. Her factory has introduced M new machines in order to process the coming N tasks. For the i-th task, the factory has to start processing it at or after day Si, process it for Pi days, and finish the task before or at day Ei. A machine can only work on one task at a time, and each task can be processed by at most one machine at a time. However, a task can be interrupted and processed on different machines on different days. 
Now she wonders whether he has a feasible schedule to finish all the tasks in time. She turns to you for help.
 

Input
On the first line comes an integer T(T<=20), indicating the number of test cases.

You are given two integer N(N<=500) and M(M<=200) on the first line of each test case. Then on each of next N lines are three integers Pi, Si and Ei (1<=Pi, Si, Ei<=500), which have the meaning described in the description. It is guaranteed that in a feasible schedule every task that can be finished will be done before or at its end day.
 

Output
For each test case, print “Case x: ” first, where x is the case number. If there exists a feasible schedule to finish all the tasks, print “Yes”, otherwise print “No”.

Print a blank line after each test case.
 

Sample Input
24 31 3 5 1 1 42 3 73 5 92 22 1 31 2 2
 

Sample Output
Case 1: Yes Case 2: Yes
 

Author
allenlowesy
 

Source
2010 ACM-ICPC Multi-University Training Contest(13)——Host by UESTC
 

Recommend
zhouzeyong
 


/************************************************Desiner:hltime:2015/11/01Exe.Time:187MSExe.Memory:5776K题意:有M个机器,有N个任务。每个任务必须在Si 或者以后开始做,在Ei 或者之前完成,完成任务必须处理Pi 个时间单位。其中,每个任务可以在任意(空闲)机器上工作,每个机器的同一时刻只能工作一个任务,每个任务在同一时刻只能被一个机器工作,而且任务做到一半可以打断,拿去其他机器做。问:能否在规定时间内把任务做完。 题解:源点到每个任务建立一条值为完成该任务需要的天数的边任务到该任务开始到该任务结束的所有天数分别建立一条为1的边天数到汇点建立一条为题目中机械数量的边如果sap算出来的结果是等于他所需要的天数的。说明他们能完成 ************************************************/#include <iostream>    #include <algorithm>    #include <cstring>    #include <string>    #include <cstdio>    #include <cmath>          using namespace std;    const int MAXN = 100010 ; //点数最大值      const int MAXM = 400010 ; //边数最大值      const int INF = 0x3f3f3f3f;        int S,V,N,M;  int maxday; struct Edge{          int to,next,cap,flow;      }edge[MAXM];//注意是MAXM      int tol;      int head[MAXN];      int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];       int aa[555],bb[555],cc[555];       void init(){          tol = 0;          memset(head,-1,sizeof(head));      }           void addedge(int u,int v,int w,int rw=0){          edge[tol].to = v;          edge[tol].cap = w;          edge[tol].next = head[u];          edge[tol].flow = 0;          head[u] = tol++;          edge[tol].to = u;          edge[tol].cap = rw;          edge[tol].next = head[v];          edge[tol].flow = 0;          head[v] = tol++;      }        //最大流开始     int sap(int start,int end,int N){          memset(gap,0,sizeof(gap));          memset(dep,0,sizeof(dep));          memcpy(cur,head,sizeof(head));          int u = start;          pre[u] = -1;          gap[0] = N;          int ans = 0;          while(dep[start] < N){              if(u==end){                  int Min = INF;                  for(int i=pre[u];i!= -1; i=pre[edge[i^1].to])                      if(Min > edge[i].cap - edge[i].flow)                          Min = edge[i].cap - edge[i].flow;                                            for(int i=pre[u];i!=-1;i=pre[edge[i^1].to]){                      edge[i].flow += Min;                      edge[i^1].flow -=Min;                  }                  u=start;                  ans +=Min;                  continue;              }              bool flag = false;              int v;              for(int i= cur[u];i!=-1;i=edge[i].next){                  v=edge[i].to;                  if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]){                      flag=true;                      cur[u]=pre[v]=i;                      break;                  }              }              if(flag){                  u=v;                  continue;              }              int Min = N;              for(int i=head[u];i!= -1;i=edge[i].next)                  if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min){                      Min=dep[edge[i].to];                      cur[u] = i;                  }              gap[dep[u]]--;              if(!gap[dep[u]]) return ans;              dep[u] = Min +1;              gap[dep[u]]++;              if(u!=start) u = edge[pre[u]^1].to;          }          return ans;      }      //最大流结束       int build(){      int i,j,k,l,m,n;      init();      for(i=1;i<=N;i++){         addedge(S,i,aa[i]);//源点到每个任务的连线为PI        for(j=bb[i];j<=cc[i];j++){       addedge(i,N+j,1); //从这个任务到这个任务开始的时间到结束的时间连一条为1的边        }    } for(j=1;j<=maxday;j++){addedge(j+N,V,M); }    int orz=sap(S,V,V+1);      return orz;        }        bool solve(int su){        int i,j,k;      int ans;     ans = build();    if(ans==su){    printf("Yes\n");    }     else{    printf("No\n");    }      }        int main(){     int T;    int m,n,q,p;          int i,j,k,a,b,c; int pisum;  scanf("%d",&T);    for(int cas=1;cas<=T;cas++){    scanf("%d%d",&N,&M);   pisum=maxday=0;    for(i=1;i<=N;i++){          scanf("%d%d%d",&aa[i],&bb[i],&cc[i]);  pisum+=aa[i];maxday=max(maxday,cc[i]);    }     S=0;    V=N+maxday+1;    printf("Case %d: ",cas);     solve(pisum);puts("");    }         return 0;  }      


0 0
原创粉丝点击