zoukankan      html  css  js  c++  java
  • UVa11167 Monkeys in the Emei Mountain(最大流)

    题目大概说有n只猴子,猴子们在某个时间段需要喝vi时间的水,各个单位时间段最多允许m只猴子同时喝水,问猴子们能否成功喝水并输出一个可行的方案,输出方案的时间段区间要从小到大排序并且合并连续的区间。

    首先应该能联想到这是最大流的模型。猴子有100只,不过区间的点达到50W,这时考虑离散化,离散化后最多就200个点也就是199个区间。

    • 于是猴子与区间可以作为容量网络的点,新建源点和汇点。
    • 源点向猴子连容量vi的边,区间向汇点连容量为区间包含单位时间段数*m的边。
    • 各个猴子喝水时间段包含的区间,由猴子向区间连容量为区间包含单位时间段数的边。

    这个建图很容易想到。不过这题不是这么容易就解决了。。还要输出方案。

    在残量网络中能知道各个猴子使用的哪几个区间中的多少个时间段。可以通过这个信息去构造出一个可行的方案:从头到尾再回到头循环地把区间内各个时间段安排给各个猴子。

    最后得到区间还要排序下。。然后合并连续区间。。我WA了好久,搞了好久。。合并区间写错了。。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 #include<algorithm>
      5 using namespace std;
      6 #define INF (1<<30)
      7 #define MAXN 333
      8 #define MAXM 333*666
      9 
     10 struct Edge{
     11     int v,cap,next;
     12 }edge[MAXM];
     13 int vs,vt,NE,NV;
     14 int head[MAXN];
     15 
     16 void addEdge(int u,int v,int cap){
     17     edge[NE].v=v; edge[NE].cap=cap;
     18     edge[NE].next=head[u]; head[u]=NE++;
     19     edge[NE].v=u; edge[NE].cap=0;
     20     edge[NE].next=head[v]; head[v]=NE++;
     21 }
     22 
     23 int level[MAXN];
     24 int gap[MAXN];
     25 void bfs(){
     26     memset(level,-1,sizeof(level));
     27     memset(gap,0,sizeof(gap));
     28     level[vt]=0;
     29     gap[level[vt]]++;
     30     queue<int> que;
     31     que.push(vt);
     32     while(!que.empty()){
     33         int u=que.front(); que.pop();
     34         for(int i=head[u]; i!=-1; i=edge[i].next){
     35             int v=edge[i].v;
     36             if(level[v]!=-1) continue;
     37             level[v]=level[u]+1;
     38             gap[level[v]]++;
     39             que.push(v);
     40         }
     41     }
     42 }
     43 
     44 int pre[MAXN];
     45 int cur[MAXN];
     46 int ISAP(){
     47     bfs();
     48     memset(pre,-1,sizeof(pre));
     49     memcpy(cur,head,sizeof(head));
     50     int u=pre[vs]=vs,flow=0,aug=INF;
     51     gap[0]=NV;
     52     while(level[vs]<NV){
     53         bool flag=false;
     54         for(int &i=cur[u]; i!=-1; i=edge[i].next){
     55             int v=edge[i].v;
     56             if(edge[i].cap && level[u]==level[v]+1){
     57                 flag=true;
     58                 pre[v]=u;
     59                 u=v;
     60                 //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
     61                 aug=min(aug,edge[i].cap);
     62                 if(v==vt){
     63                     flow+=aug;
     64                     for(u=pre[v]; v!=vs; v=u,u=pre[u]){
     65                         edge[cur[u]].cap-=aug;
     66                         edge[cur[u]^1].cap+=aug;
     67                     }
     68                     //aug=-1;
     69                     aug=INF;
     70                 }
     71                 break;
     72             }
     73         }
     74         if(flag) continue;
     75         int minlevel=NV;
     76         for(int i=head[u]; i!=-1; i=edge[i].next){
     77             int v=edge[i].v;
     78             if(edge[i].cap && level[v]<minlevel){
     79                 minlevel=level[v];
     80                 cur[u]=i;
     81             }
     82         }
     83         if(--gap[level[u]]==0) break;
     84         level[u]=minlevel+1;
     85         gap[level[u]]++;
     86         u=pre[u];
     87     }
     88     return flow;
     89 }
     90 
     91 int need[111],x[111],y[111];
     92 int point[222],pn;
     93 
     94 struct Interval{
     95     int x,y;
     96     bool operator<(const Interval &i)const{
     97         return x<i.x;
     98     }
     99 }interval[500000];
    100 
    101 int main(){
    102     int cse=0,n,m;
    103     while(~scanf("%d",&n) && n){
    104         scanf("%d",&m);
    105         pn=0; int tot=0;
    106         for(int i=1; i<=n; ++i){
    107             scanf("%d%d%d",need+i,x+i,y+i);
    108             tot+=need[i];
    109             point[pn++]=x[i];
    110             point[pn++]=y[i];
    111         }
    112         sort(point,point+pn);
    113         pn=unique(point,point+pn)-point;
    114 
    115         vs=0; vt=n+pn+1; NV=vt+1; NE=0;
    116         memset(head,-1,sizeof(head));
    117 
    118         for(int i=1; i<pn; ++i){
    119             addEdge(i+n,vt,m*(point[i]-point[i-1]));
    120         }
    121         for(int i=1; i<=n; ++i){
    122             addEdge(vs,i,need[i]);
    123             int from=lower_bound(point,point+pn,x[i])-point;
    124             int to=lower_bound(point,point+pn,y[i])-point;
    125             for(int j=from+1; j<=to; ++j){
    126                 addEdge(i,j+n,point[j]-point[j-1]);
    127             }
    128         }
    129 
    130         if(ISAP()!=tot){
    131             printf("Case %d: No
    ",++cse);
    132             continue;
    133         }
    134         printf("Case %d: Yes
    ",++cse);
    135 
    136         int cnt[222]={0};
    137 
    138         for(int u=1; u<=n; ++u){
    139             int in=0;
    140             for(int i=head[u]; i!=-1; i=edge[i].next){
    141                 if(i&1 || edge[i^1].cap==0) continue;
    142                 int k=edge[i].v-n,tot=point[k]-point[k-1];
    143                 if(cnt[k]+edge[i^1].cap<=tot){
    144                     interval[in].x=point[k-1]+cnt[k];
    145                     interval[in].y=point[k-1]+cnt[k]+edge[i^1].cap;
    146                     ++in;
    147                     cnt[k]+=edge[i^1].cap;
    148                 }else if(cnt[k]==tot){
    149                     interval[in].x=point[k-1];
    150                     interval[in].y=point[k-1]+edge[i^1].cap;
    151                     ++in;
    152                     cnt[k]=edge[i^1].cap;
    153                 }else{
    154                     interval[in].x=point[k-1]+cnt[k];
    155                     interval[in].y=point[k];
    156                     ++in;
    157                     cnt[k]+=edge[i^1].cap; cnt[k]-=tot;
    158                     interval[in].x=point[k-1];
    159                     interval[in].y=point[k-1]+cnt[k];
    160                     ++in;
    161                 }
    162             }
    163             sort(interval,interval+in);
    164             int tot=in;
    165             for(int i=1; i<in; ++i){
    166                 if(interval[i].x==interval[i-1].y){
    167                     --tot;
    168                 }
    169             }
    170             printf("%d",tot);
    171             for(int i=0; i<in; ){
    172                 int j=i+1;
    173                 while(j<in && interval[j-1].y==interval[j].x){
    174                     ++j;
    175                 }
    176                 printf(" (%d,%d)",interval[i].x,interval[j-1].y);
    177                 i=j;
    178             }
    179             putchar('
    ');
    180         }
    181     }
    182     return 0;
    183 }
  • 相关阅读:
    mac 版 Pycharm 激活
    最快的 maven repository--阿里镜像仓库
    java-Object
    java --replaceAll方法
    正则表达式中^[a-z]与[^a-z]有区别吗
    keyListener用的健值表,保留一份
    java播放背景音乐 mp3和mav都可以播放
    腾讯云ubuntu远程桌面
    nginx 配置转发到其他多台服务器
    java 键盘监听事件
  • 原文地址:https://www.cnblogs.com/WABoss/p/5724862.html
Copyright © 2011-2022 走看看