Problem C
Monkeys in the Emei Mountain
Input: Standard Input
Output: Standard Output
Xuexue is a pretty monkey living in the Emei mountain. She is extremely thirsty during time 2 and time 9 everyday, so she must drink 2 units water during this period. She may drink water more than once, as long as the total amount of water she drinks is exactly 2 - she never drinks more than she needs. Xuexue drinks 1 unit water in one time unit, so she may drinks from time 2 to time 4, or from 3 to 5, … , or from 7 to 9, or even drinks twice: first from 2 to 3, then from 8 to 9. But she can't drink from 1 to 3 since she's not thirsty at time 1, and she can't drink from 8 to 10, since she must finish at time 9.
There are many monkeys like Xuexue: we use a triple (v, a, b) to describe a monkey who is thirsty during time a and b, and must drink exactly v units of water during that period. Every monkey drinks at the same speed (i.e. one unit water per unit time).
Unfortunately, people keep on doing something bad on the environment in Emei Mountain. Eventually, there are only one unpolluted places for monkeys to drink. Further more, the place is so small that at most m monkeys can drink water together. Monkeys like to help each other, so they want to find a way to satisfy all the monkeys' need. Could you help them?
Input
The input consists of several test cases. Each case contains two integers n and m (1 £ n £ 100, 1 £ m £ 5), followed by n lines of three integer numbers (v, a, b), where 0 £ v, a, b £ 50,000, a < b, v £ b - a. The last test case is followed by a single zero, which should not be processed. There are at most 50 test cases.
Output
For each test case, print the case number and whether there is a solution. If there is a solution, the following n lines describe the solution: one monkey on a separate line. The first number k means the monkey drinks water for k times. The following k pairs (ai, bi) means the monkey drinks from ai to bi (ai< bi). The pairs should be sorted in ascending order, and ai should not be equal to ai+1 for 1£ i £ k-1 (otherwise these two drinking periods could be combined). If more than one solution exists, any one is acceptable. Note that there should be exactly one space between k and pairs (ai,bi), but no space within each pair.
Sample Input Output for Sample Input
3 1 2 2 9 2 3 5 3 5 8 2 1 4 5 9 4 8 12 5 2 2 1 3 2 3 5 2 5 7 2 1 7 4 2 6 0 | Case 1: Yes 2 (2,3) (8,9) 1 (3,5) 1 (5,8) Case 2: No Case 3: Yes 1 (1,3) 1 (3,5) 1 (5,7) 2 (1,2) (6,7) 1 (2,6) |
Original Author: Dong Zhou
Adapted by Rujia Liu (Problem description, Special judge)
Alternative Solution: Huayang Guo
WA掉的代码。。。
建模:区间压缩(interval contraction,很多题解叫“离散化”),然后把时间区间缩小至[1, 200),建立至多199个区间,每个长度为1(hash长度可能不同);
接着从源点引边至每个区间,容量为m*(hash[left+1] - hash[left]);从每个区间向可以在该时段解渴的猴子引容量为(hash[left+1] - hash[left])的边(记下这条边),从每只猴子向汇点引容量为饥渴度的边。。。
最后,枚举每只猴子对应的所有解渴时段,对应流量找可行区间(reverse hash / contraction)即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define UINT unsigned int
#define MAX_INT 0x7fffffff
#define cint const int
#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
#define INF 100000000
#define MAXN 310
#define MAXM 41000
#define MAXK 55555
#define MAX_MONKEY 111
#define MAX_INTERVAL 222
struct MON{
int v, a, b;
}monkey[MAX_MONKEY];
int contract[MAXK];
int rcontract[MAX_INTERVAL];
struct edge{
int u, v, cap, flow, nxt;
}e[MAXM];
int h[MAXN], cc;
void add(int u, int v, int cap){
e[cc]=(edge){u, v, cap, 0, h[u]};
h[u]=cc++;
e[cc]=(edge){v, u, 0, 0, h[v]};
h[v]=cc++;
}
int p[MAXN], num[MAXN], cur[MAXN], vis[MAXN];
int d[MAXN];
void rbfs(cint t){
queue<int> q; q.push(t);
memset(vis, 0, sizeof(vis));
d[t]=0; vis[t]=1;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=h[u]; i!=-1; i=e[i].nxt){
i^=1;
int v=e[i].u, cap=e[i].cap, ef=e[i].flow;
if(!vis[v] && cap>ef){
vis[v]=1;
d[v]=d[u]+1;
q.push(v);
}
i^=1;
}
}
}
int Augment(cint s, cint t){
int a=INF, u;
for(u=t; u!=s; u=e[p[u]].u)
a=MIN(a, e[p[u]].cap-e[p[u]].flow);
for(u=t; u!=s; u=e[p[u]].u){
int i=p[u];
e[i].flow+=a;
e[i^1].flow-=a;
}
return a;
}
int isap(cint s, cint t, cint n){
int i, flow=0;
rbfs(t);
memset(num, 0, sizeof(num));
for(i=0; i<n; i++) num[d[i]]++;
for(i=0; i<n; i++) cur[i]=h[i];
for(int u=s; d[s]<n; ){
if(u==t){
flow+=Augment(s, t);
u=s;
}
bool ok=false;
for(i=cur[u]; i!=-1; i=e[i].nxt){
int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
if(d[v]+1==d[u] && cap>ef){
ok=true;
p[v]=i;
cur[u]=i;
u=v;
break;
}
}
if(!ok){
int tmp=n-1;
for(i=h[u]; i!=-1; i=e[i].nxt){
int v=e[i].v, cap=e[i].cap, ef=e[i].flow;
if(cap>ef) tmp=MIN(tmp, d[v]);
}
if(--num[d[u]]==0) break;
num[d[u]=tmp+1]++;
cur[u]=h[u];
if(u!=s) u=e[p[u]].u;
}
}
return flow;
}
int cover_times[MAXK];
int can_drink[MAX_INTERVAL];
vector<int> drink[MAX_MONKEY];
int print(cint n, cint m, cint cnt){
int i, j;
memset(cover_times, 0, sizeof(cover_times)); //cover_times[i]为区间[i, i+1)的覆盖次数,即这个时段有多少monkey喝水
for(i=1; i<=cnt; i++) can_drink[i]=rcontract[i]; //初始时没有monkey喝水
for(i=0; i<n; i++){
int prer=-1;
vector<int> lft, rit;
for(j=0; j<drink[i].size(); j++){
int drinked = e[drink[i][j]].flow, u=e[drink[i][j]].u-n;
int l=can_drink[u]/*, r=rcontract[u+1]*/;
if(!drinked) continue;
cint ansl=l, ansr=l+drinked;
while(drinked--) cover_times[l++]++;
while(cover_times[can_drink[u]]>=m) can_drink[u]++;
if(ansl==prer) rit[rit.size()-1]=ansr;
else{
lft.push_back(ansl);
rit.push_back(ansr);
}
prer=ansr;
}
printf("%d", lft.size());
for(j=0; j<lft.size(); j++)
printf(" (%d,%d)", lft[j], rit[j]);
printf("\n");
}
return 0;
}
int main(){
// freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
int kase=1, cnt, n, m;
while(scanf(" %d", &n)==1 && n){
int i, v, a, b, need_water=0;
scanf(" %d", &m);
memset(contract, 0, sizeof(contract));
for(i=0; i<n; i++){
scanf(" %d %d %d", &v, &a, &b);
monkey[i]=(MON){v, a, b};
need_water+=v;
contract[a]=contract[b]=1; // a==b ?
}
for(cnt=i=0; i<MAXK; i++) if(contract[i]){
contract[i]=++cnt;
rcontract[cnt]=i;
}
memset(h, -1, sizeof(h)); cc=0;
for(i=1; i<cnt; i++)
add(0, i+n, m*(rcontract[i+1] - rcontract[i]));
for(i=0; i<n; i++){
int v=monkey[i].v, a=contract[monkey[i].a], b=contract[monkey[i].b];
drink[i].clear();
if(!v) continue;
for(int j=a; j<b; j++){
drink[i].push_back(cc);
add(j+n, i+1, rcontract[j+1] - rcontract[j]);
}
add(i+1, n+cnt+1, v);
}
if(isap(0, n+cnt+1, n+cnt+2)<need_water) printf("Case %d: No\n", kase++);
else printf("Case %d: Yes\n", kase++), print(n, m, cnt);
}
return 0;
}