题意:有N个任务和M台机器。对于每个任务i,它必须在第Si天或之后开始执行,完成这个任务需要Pi天,并且必须在第Ei天或其之前完成。一台机器在同一时间段内只能做一个任务,一个任务在同一时间段内也只能被一台机器执行。任务可以被打断执行,可以在不同的时间在不同的机器上进行。现在给出这些数据,问是否有可行的调度方案。
每天每台机器只能完成一个工作量,那么把这个工作量作为流量是比较合理的。题目里面有三个量,时间,机器,任务。注意,根据题意,每台机器每天只能完成一个工作量,我们可以说每天给我M台机器我可以每天完成M个工作量,因此只要保留两个量作为图中的点:天数,任务,图中的流量对应工作量。那么对于所有任务,可以对应一条从源点连向它的边(S,i,process),对于每天j,对应边(j,T,M),而如果第i个任务可以在第j天做,对应一条边(i,j,1),跑最大流,如果满流,就OK。

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #define INF 0x7fffffff 6 #define maxn 1010 7 #define maxm 300000 8 using namespace std; 9 int v[maxm],next[maxm],w[maxm]; 10 int first[maxn],d[maxn],work[maxn],q[maxn]; 11 int e,S,T; 12 13 void init(){ 14 e = 0; 15 memset(first,-1,sizeof(first)); 16 } 17 18 void add_edge(int a,int b,int c){ 19 //printf("add:%d to %d,cap = %d ",a,b,c); 20 v[e] = b;w[e] = c;next[e] = first[a];first[a] = e++; 21 v[e] = a;w[e] = 0;next[e] = first[b];first[b] = e++; 22 } 23 24 int bfs(){ 25 int rear = 0; 26 memset(d,-1,sizeof(d)); 27 d[S] = 0;q[rear++] = S; 28 for(int i = 0;i < rear;i++){ 29 for(int j = first[q[i]];j != -1;j = next[j]) 30 if(w[j] && d[v[j]] == -1){ 31 d[v[j]] = d[q[i]] + 1; 32 q[rear++] = v[j]; 33 if(v[j] == T) return 1; 34 } 35 } 36 return 0; 37 } 38 39 int dfs(int cur,int a){ 40 if(cur == T) return a; 41 for(int &i = work[cur];i != -1;i = next[i]){ 42 if(w[i] && d[v[i]] == d[cur] + 1) 43 if(int t = dfs(v[i],min(a,w[i]))){ 44 w[i] -= t;w[i^1] += t; 45 return t; 46 } 47 } 48 return 0; 49 } 50 51 int dinic(){ 52 int ans = 0; 53 while(bfs()){ 54 memcpy(work,first,sizeof(first)); 55 while(int t = dfs(S,INF)) ans += t; 56 } 57 return ans; 58 } 59 60 int main() 61 { 62 int ncase,n,m; 63 scanf("%d",&ncase); 64 for(int kase = 1;kase <= ncase;kase++){ 65 init(); 66 scanf("%d%d",&n,&m); 67 S = 0,T = 1001; 68 int sum = 0; 69 for(int i = 1;i <= n;i++){ 70 int start,process,end; 71 scanf("%d%d%d",&process,&start,&end); 72 sum += process; 73 add_edge(S,i,process); 74 for(int j = start;j <= end;j++) 75 add_edge(i,500+j,1); 76 } 77 for(int i = 501;i <= 1000;i++) 78 add_edge(i,T,m); 79 bool flag = true; 80 int tmp = dinic(); 81 //printf("tmp = %d ",tmp); 82 if(tmp != sum) flag = false; 83 printf("Case %d: ",kase); 84 if(flag) printf("Yes "); 85 else printf("No "); 86 } 87 return 0; 88 }