首页 > 代码库 > hdu 3572 Task Schedule 网络流

hdu 3572 Task Schedule 网络流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572
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.
 
题意:有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 }

 

hdu 3572 Task Schedule 网络流