UVa11167 Monkeys in the Emei Mountain(最大流)
题目大概说有n只猴子,猴子们在某个时间段需要喝vi时间的水,各个单位时间段最多允许m只猴子同时喝水,问猴子们能否成功喝水并输出一个可行的方案,输出方案的时间段区间要从小到大排序并且合并连续的区间。
首先应该能联想到这是最大流的模型。猴子有100只,不过区间的点达到50W,这时考虑离散化,离散化后最多就200个点也就是199个区间。
- 于是猴子与区间可以作为容量网络的点,新建源点和汇点。
- 源点向猴子连容量vi的边,区间向汇点连容量为区间包含单位时间段数*m的边。
- 各个猴子喝水时间段包含的区间,由猴子向区间连容量为区间包含单位时间段数的边。
这个建图很容易想到。不过这题不是这么容易就解决了。。还要输出方案。
在残量网络中能知道各个猴子使用的哪几个区间中的多少个时间段。可以通过这个信息去构造出一个可行的方案:从头到尾再回到头循环地把区间内各个时间段安排给各个猴子。
最后得到区间还要排序下。。然后合并连续区间。。我WA了好久,搞了好久。。合并区间写错了。。
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 333
#define MAXM 333*666 struct Edge{
int v,cap,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-,sizeof(level));
memset(gap,,sizeof(gap));
level[vt]=;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-) continue;
level[v]=level[u]+;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=,aug=INF;
gap[]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap && level[u]==level[v]+){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].cap-=aug;
edge[cur[u]^].cap+=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==) break;
level[u]=minlevel+;
gap[level[u]]++;
u=pre[u];
}
return flow;
} int need[],x[],y[];
int point[],pn; struct Interval{
int x,y;
bool operator<(const Interval &i)const{
return x<i.x;
}
}interval[]; int main(){
int cse=,n,m;
while(~scanf("%d",&n) && n){
scanf("%d",&m);
pn=; int tot=;
for(int i=; i<=n; ++i){
scanf("%d%d%d",need+i,x+i,y+i);
tot+=need[i];
point[pn++]=x[i];
point[pn++]=y[i];
}
sort(point,point+pn);
pn=unique(point,point+pn)-point; vs=; vt=n+pn+; NV=vt+; NE=;
memset(head,-,sizeof(head)); for(int i=; i<pn; ++i){
addEdge(i+n,vt,m*(point[i]-point[i-]));
}
for(int i=; i<=n; ++i){
addEdge(vs,i,need[i]);
int from=lower_bound(point,point+pn,x[i])-point;
int to=lower_bound(point,point+pn,y[i])-point;
for(int j=from+; j<=to; ++j){
addEdge(i,j+n,point[j]-point[j-]);
}
} if(ISAP()!=tot){
printf("Case %d: No\n",++cse);
continue;
}
printf("Case %d: Yes\n",++cse); int cnt[]={}; for(int u=; u<=n; ++u){
int in=;
for(int i=head[u]; i!=-; i=edge[i].next){
if(i& || edge[i^].cap==) continue;
int k=edge[i].v-n,tot=point[k]-point[k-];
if(cnt[k]+edge[i^].cap<=tot){
interval[in].x=point[k-]+cnt[k];
interval[in].y=point[k-]+cnt[k]+edge[i^].cap;
++in;
cnt[k]+=edge[i^].cap;
}else if(cnt[k]==tot){
interval[in].x=point[k-];
interval[in].y=point[k-]+edge[i^].cap;
++in;
cnt[k]=edge[i^].cap;
}else{
interval[in].x=point[k-]+cnt[k];
interval[in].y=point[k];
++in;
cnt[k]+=edge[i^].cap; cnt[k]-=tot;
interval[in].x=point[k-];
interval[in].y=point[k-]+cnt[k];
++in;
}
}
sort(interval,interval+in);
int tot=in;
for(int i=; i<in; ++i){
if(interval[i].x==interval[i-].y){
--tot;
}
}
printf("%d",tot);
for(int i=; i<in; ){
int j=i+;
while(j<in && interval[j-].y==interval[j].x){
++j;
}
printf(" (%d,%d)",interval[i].x,interval[j-].y);
i=j;
}
putchar('\n');
}
}
return ;
}
UVa11167 Monkeys in the Emei Mountain(最大流)的更多相关文章
- UVA-11167 Monkeys in the Emei Mountain(区间模型最大流+输出方案)
题目大意:有n只猴子,每只猴子都有一组参数(v,a,b),表示这只猴子在时间段[a,b]之间必须要喝v个单位水,并且每个时间单位只能和一个单位水,每次至少喝一个单位.但是只有一个水池,并且这个水池最多 ...
- UVa 11167 Monkeys in the Emei Mountain (最大流)
题意:雪雪是一只猴子.它在每天的 2:00 —— 9:00之间非常渴,所以在这个期间它必须喝掉2个单位的水.它可以多次喝水,只要它喝水的总量是2.它从不多喝,在一小时内他只能喝一个单位的水.所以它喝水 ...
- Codeforces Gym 100733I The Cool Monkeys 拆点+最大流
原题链接:http://codeforces.com/gym/100733/problem/I 题意 有两颗树(只是树,不是数据结构),每棵树上有不同高度的树枝,然后有m只猴子在某棵树的前m高的树枝上 ...
- 【bzoj2929】[Poi1999]洞穴攀行 网络流最大流
题目描述 洞穴学者在Byte Mountain的Grate Cave里组织了一次训练.训练中,每一位洞穴学者要从最高的一个室到达最底下的一个室.他们只能向下走.一条路上每一个连续的室都要比它的前一个低 ...
- IO流10 --- 缓冲流(字节型)实现非文本文件的复制 --- 技术搬运工(尚硅谷)
字节型缓冲流,BufferedOutputStream默认缓冲区大小 8192字节byte,满了自动flush() @Test public void test6(){ File srcFile = ...
- 使用C#处理基于比特流的数据
使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...
- HTML 事件(三) 事件流与事件委托
本篇主要介绍HTML DOM中的事件流和事件委托. 其他事件文章 1. HTML 事件(一) 事件的介绍 2. HTML 事件(二) 事件的注册与注销 3. HTML 事件(三) 事件流与事件委托 4 ...
- FILE文件流的中fopen、fread、fseek、fclose的使用
FILE文件流用于对文件的快速操作,主要的操作函数有fopen.fseek.fread.fclose,在对文件结构比较清楚时使用这几个函数会比较快捷的得到文件中具体位置的数据,提取对我们有用的信息,满 ...
- java.IO输入输出流:过滤流:buffer流和data流
java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...
随机推荐
- 通过颜色代码初始化UIColor
#define UIColorFromHEX(rgbValue) [UIColor \ colorWithRed:((float)((rgbValue & 0xFF0000) >> ...
- [Android Pro] Java进阶学习:jar打包详解
jar文件听说过吗,没有?或者陌生!好,没关系,这就是我们的第一站:打包发布. 为什么会有这个玩意呢,首先,这是jar的全称:JavaTM Archive (JAR) file,是的,就是java存档 ...
- 树形DP习题
听闻noip要考树形DP,本蒟蒻万分惶恐,特刷一坨题目,以慰受惊之心. codevs 1486 /*和非常出名的"选课"是一个题*/ #include<cstdio> ...
- c++ 头文件包含问题-include&class
http://blog.csdn.net/jiajia4336/article/details/8996254 前向声明概念(forward declaration) 在程序中引入了类类型的B.在声明 ...
- Swift - 代码创建单例
创建单例的方法 import UIKit //创建一个单例类 class SingleInstance: NSObject { //在单例类中,有一个用来共享数据的数组 var datas = [St ...
- Git+VirtalBaox+Vagrant创建Linux虚拟机
文章内容来自Udacity课程:Linux Command Line Basics--Getting Started with the Shell Your own Linux box To lear ...
- Enter password for default keyring to unlock
file /home/ok/.gnome2/keyrings/login.keyring /home/ok/.gnome2/keyrings/login.keyring: GNOME keyring, ...
- SQLServer子查询
in谓词子查询 select * from dbo.Worker where did in (select dID from DepartMent) 比较运算子查询 select * from Wor ...
- 新手上路之Hibernate:第一个Hibernate例子
一.Hibernate概述 (一)什么是Hibernate? Hibernate核心内容是ORM(关系对象模型).可以将对象自动的生成数据库中的信息,使得开发更加的面向对象.这样作为程序员就可以使用面 ...
- Java Socket编程示例
一.Socket简介: 1.什么是Socket 网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket ...