• 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         
  • 相关阅读:
    逆元模板
    同余方程
    计算系数
    Mayan游戏
    【分治】聪明的质检员(二分)
    瑞士轮(归并排序)
    极值问题
    传纸条
    2014-2015-1学期学习计划
    桌面综合实训答辩验收详情
  • 原文地址:https://www.cnblogs.com/wally/p/3056726.html
Copyright © 2020-2023  润新知