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