hdu 3572 Task Schedule 网络流
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.
Now she wonders whether he has a feasible schedule to finish all the tasks in time. She turns to you for help.
题意:有M台机器和N个任务,每个任务必须在第si天到第ei天之间完成,完成一个任务需要pi天(1<=i<=n)。一台机器同时只能做一个任务,一个任务同一时间只能由一台机器处理。问能否完成。
解法:构造成为网络流,然后运用SAP算法求解。
把每个任务和每个时刻都作为节点,增设一个源点和一个汇点。对于任务i,连接一条源点指向 i 最大容量为pi 的边,然后连接 i 到[ si , ei ]区间里每个时刻,最大容量为1,最后连接每个时刻到汇点,最大容量为m(因为同一时刻最多只能有m台机器在操作)。此时,完成构图。
用网络流算法求解到最大流之后,判断是不是满流(每个任务都有天数的限制,不能少也不能多)。
SAP和Dinic算法:这道题里节点1000,边数50w,Dinic+邻接矩阵是不行的了,看到hdu上面有人800+msAC,也许Dinic+邻接表吧。我直接选用各种优化之后的SAP算法。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #define inf 0x7fffffff 9 using namespace std; 10 const int maxn=1000+10; 11 const int M = 500000+10; 12 13 struct Edge 14 { 15 int to,cap,next; 16 }edge[M]; 17 int head[maxn],edgenum; 18 int n,m,from,to,vnum; 19 int level[maxn],gap[maxn]; 20 21 void add(int u,int v,int cap) 22 { 23 edge[edgenum].to=v; 24 edge[edgenum].cap=cap; 25 edge[edgenum].next=head[u]; 26 head[u]=edgenum++; 27 28 edge[edgenum].to=u; 29 edge[edgenum].cap=0; 30 edge[edgenum].next=head[v]; 31 head[v]=edgenum++; 32 } 33 34 void bfs(int to) 35 { 36 memset(level,-1,sizeof(level)); 37 memset(gap,0,sizeof(gap)); 38 level[to]=0; 39 gap[level[to] ]++; 40 queue<int> Q; 41 Q.push(to); 42 while (!Q.empty()) 43 { 44 int u=Q.front() ;Q.pop() ; 45 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 46 { 47 int v=edge[i].to; 48 if (level[v] != -1) continue; 49 level[v]=level[u]+1; 50 gap[level[v] ]++; 51 Q.push(v); 52 } 53 } 54 } 55 56 int pre[maxn]; 57 int cur[maxn]; 58 int SAP(int from,int to) 59 { 60 bfs(to); 61 memset(pre,-1,sizeof(pre)); 62 memcpy(cur,head,sizeof(head)); 63 int u=pre[from]=from,flow=0,aug=inf; 64 gap[0]=vnum; 65 while (level[from]<vnum) 66 { 67 bool flag=false; 68 for (int &i=cur[u] ;i!=-1 ;i=edge[i].next) 69 { 70 int v=edge[i].to; 71 if (edge[i].cap>0 && level[u]==level[v]+1) 72 { 73 flag=true; 74 pre[v]=u; 75 u=v; 76 aug=min(aug,edge[i].cap); 77 if (u==to) 78 { 79 flow += aug; 80 for (u=pre[u] ;v!=from ;v=u,u=pre[u]) 81 { 82 edge[cur[u] ].cap -= aug; 83 edge[cur[u]^1 ].cap += aug; 84 } 85 aug=inf; 86 } 87 break; 88 } 89 } 90 if (flag) continue; 91 int minlevel=vnum; 92 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 93 { 94 int v=edge[i].to; 95 if (edge[i].cap>0 && level[v]<minlevel) 96 { 97 minlevel=level[v]; 98 cur[u]=i; 99 } 100 } 101 if (--gap[level[u] ]==0) break; 102 level[u]=minlevel+1; 103 gap[level[u] ]++; 104 u=pre[u]; 105 } 106 return flow; 107 } 108 109 int main() 110 { 111 int t,ncase=1; 112 scanf("%d",&t); 113 while (t--) 114 { 115 scanf("%d%d",&n,&m); 116 int p,s,e; 117 memset(head,-1,sizeof(head)); 118 edgenum=0; 119 from=0; 120 int sn[501],en[501],maxe=0; 121 int sum=0; 122 for (int i=1 ;i<=n ;i++) 123 { 124 scanf("%d%d%d",&p,&s,&e); 125 sum += p; 126 sn[i]=s ;en[i]=e ; 127 maxe=max(maxe,e); 128 add(from,i,p); 129 for (int j=s ;j<=e ;j++) 130 { 131 add(i,n+j,1); 132 } 133 } 134 to=maxe+1; 135 vnum=to+1; 136 for (int j=1 ;j<=maxe ;j++) 137 add(n+j,to,m); 138 int Maxflow=SAP(from,to); 139 printf("Case %d: ",ncase++); 140 if (Maxflow==sum) printf("Yes\n"); 141 else printf("No\n"); 142 printf("\n"); 143 } 144 return 0; 145 }