hdu 3572(最大流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3572

先说一下题意:有M个机器,有N个任务。每个任务必须在Si 或者以后开始做,在Ei 或者之前完成,完成任务必须处理Pi 个时间单位。其中,每个任务可以在任意(空闲)机器上工作,每个机器的同一时刻只能工作一个任务,每个任务在同一时刻只能被一个机器工作,而且任务做到一半可以打断,拿去其他机器做。问:能否在规定时间内把任务做完。

思路:建图是关键,我们可以选择0为源点,然后源点与每个任务都连一条边,容量为要求的天数p,然后每个任务都与相应的时间点连边,边容量为1,最后我们要确定汇点,汇点可以取vt=max+n+1(其中max为结束时间的最大值,n为任务数),这样确定好汇点之后,再在每个时间点与汇点之间连边,边容量为m,为机器数,最后判断sum(for all pi)==?SAP即可。

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 #define MAXM 555555
  6 #define MAXN 2222
  7 struct Edge{
  8     int v,cap,next;
  9 }edge[MAXM];
 10 
 11 int pre[MAXN];
 12 int cur[MAXN];
 13 int head[MAXN];
 14 int level[MAXN];
 15 int gap[MAXN];
 16 int n,m;
 17 int NV,NE;
 18 
 19 int SAP(int vs,int vt){
 20     memset(pre,-1,sizeof(pre));
 21     memset(level,0,sizeof(level));
 22     memset(gap,0,sizeof(gap));
 23     for(int i=0;i<=NV;i++)cur[i]=head[i];
 24     int u=pre[vs]=vs,maxflow=0,aug=-1;
 25     gap[0]=NV;
 26     while(level[vs]<NV){
 27 loop:
 28         for(int &i=cur[u];i!=-1;i=edge[i].next){
 29             int v=edge[i].v;
 30             if(edge[i].cap&&level[u]==level[v]+1){
 31                 aug==-1?aug=edge[i].cap:(aug=min(aug,edge[i].cap));
 32                 pre[v]=u;
 33                 u=v;
 34                 if(v==vt){
 35                     maxflow+=aug;
 36                     for(u=pre[u];v!=vs;v=u,u=pre[u]){
 37                         edge[cur[u]].cap-=aug;
 38                         edge[cur[u]^1].cap+=aug;
 39                     }
 40                     aug=-1;
 41                 }
 42                 goto loop;
 43             }
 44         }
 45         int minlevel=NV;
 46         for(int i=head[u];i!=-1;i=edge[i].next){
 47             int v=edge[i].v;
 48             if(edge[i].cap&&minlevel>level[v]){
 49                 cur[u]=i;
 50                 minlevel=level[v];
 51             }
 52         }
 53         gap[level[u]]--;
 54         if(gap[level[u]]==0)break;
 55         level[u]=minlevel+1;
 56         gap[level[u]]++;
 57         u=pre[u];
 58     }
 59     return maxflow;
 60 }
 61 
 62 void Insert(int u,int v,int cap,int cc=0){
 63     edge[NE].cap=cap;edge[NE].v=v;
 64     edge[NE].next=head[u];head[u]=NE++;
 65 
 66     edge[NE].cap=cc;edge[NE].v=u;
 67     edge[NE].next=head[v];head[v]=NE++;
 68 }
 69 
 70 
 71 
 72 int main(){
 73     int _case,t=1,vs,vt,st,ed,p,dmax,sum;
 74     scanf("%d",&_case);
 75     while(_case--){
 76         scanf("%d%d",&n,&m);
 77         memset(head,-1,sizeof(head));
 78         NE=0,dmax=0,vs=0,sum=0;
 79         for(int i=1;i<=n;i++){
 80             scanf("%d%d%d",&p,&st,&ed);
 81             dmax=max(dmax,ed);
 82             sum+=p;
 83             Insert(vs,i,p);//源点到第i个任务添加边
 84             for(int j=st;j<=ed;j++){
 85                 Insert(i,n+j,1);//第i个任务到(时间点)添加容量为1的边
 86             }
 87         }
 88         vt=n+dmax+1;//计算汇点
 89         for(int i=1;i<=dmax;i++){
 90             Insert(n+i,vt,m);//各时间点到汇点添加容量为m的边(m为机器个数)
 91         }
 92         NV=vt+1;
 93         printf("Case %d: ",t++);
 94         if(sum==SAP(vs,vt)){
 95             puts("Yes");
 96         }else 
 97             puts("No");
 98         puts("");
 99     }
100     return 0;
101 }
102             
103         

 

posted @ 2013-05-03 15:12  ihge2k  阅读(1552)  评论(0编辑  收藏  举报