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\n",++cse); 132 continue; 133 } 134 printf("Case %d: Yes\n",++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('\n'); 180 } 181 } 182 return 0; 183 }