Monkeys in the Emei Mountain
题目:
给出N之猴子,每只猴子要喝v升的水,每个小时只能喝一升的水,并且只能在[a,b]时间段进行喝水,时间可以不连续,但是每次喝水必须是一个正的单位且不小于1小时。而喝水的地方就一个,一次只能容纳m只猴子。现在要你判断是否能在满足全部的猴子喝水。
算法:
网络流的区间模型。常规做回超时,这题跟hdu kebab的模型一样,那题利索的多。这题输出太烦人了。做了一下建图模型不想再写了。给出一个别人的博客,还有建图模型可以看我之前的区间模型分析 。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int inf=1<<29;
const int maxn=410;
const int maxm=maxn*maxn;
struct Node
{
int v;
int l;
int r;
Node(){}
Node(int sl,int sr)
{
l=sl;
r=sr;
}
bool operator < (const Node &a)const
{
if(l==a.l)
return r<a.r;
return l<a.l;
}
}monk[110];
int e,st,des,n,m,head[maxn],pnt[maxm],nxt[maxm],flow[maxm],level[maxn];
int t[300],hasuse[maxn][6],cnt;
queue<int> q;
vector<Node> arr;
void AddEdge(int u,int v,int f)
{
pnt[e]=v;nxt[e]=head[u];flow[e]=f;head[u]=e++;
pnt[e]=u;nxt[e]=head[v];flow[e]=0;head[v]=e++;
}
bool BFS(int st,int des)
{
memset(level,0,sizeof(level));
level[st]=1;
q.push(st);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=nxt[i])
if(flow[i]&&!level[pnt[i]])
{
level[pnt[i]]=level[u]+1;
q.push(pnt[i]);
}
}
return level[des];
}
int DFS(int u,int maxf)
{
if(u==des||!maxf)
return maxf;
for(int i=head[u],t;i!=-1;i=nxt[i])
if(level[pnt[i]]==level[u]+1&&(t=DFS(pnt[i],min(maxf,flow[i]))))
{
flow[i]-=t;
flow[i^1]+=t;
return t;
}
return level[u]=0;
}
int maxflow()
{
int ans=0;
while(BFS(st,des))
while(1)
{
int f=DFS(st,inf);
if(!f)
break;
ans+=f;
}
return ans;
}
void solve(int tot)
{
int ans=maxflow();
if(ans<tot)
{
printf("No\n");
return;
}
printf("Yes\n");
memset(hasuse,0,sizeof(hasuse));
for(int i=1;i<=n;i++)
{
arr.clear();
for(int j=0;j<e;j+=2)
{
if(pnt[j^1]==i&&flow[j^1]&&pnt[j]<des)
{
int index=pnt[j]-n-1;
int res=flow[j^1];
for(int k=0;k<m;k++)
{
if(hasuse[index][k]==t[index+1]-t[index])
continue;
if(hasuse[index][k]+res<=t[index+1]-t[index])
{
arr.push_back(Node(t[index]+hasuse[index][k],t[index]+hasuse[index][k]+res));
hasuse[index][k]+=res;
break;
}
else
{
res-=(t[index+1]-t[index]-hasuse[index][k]);
arr.push_back(Node(t[index]+hasuse[index][k],t[index+1]));
hasuse[index][k]=t[index+1]-t[index];
if(!res)
break;
}
}
}
}
sort(arr.begin(),arr.end());
int index=0;
for(int j=1;j<arr.size();j++)
{
if(arr[j].l==arr[j-1].r)
{
arr[j-1].r=arr[j].r;
arr.erase(arr.begin()+j);
j--;
}
}
printf("%d",arr.size());
if(arr.size()==0)
printf(" (0,0)");
for(int j=0;j<arr.size();j++)
printf(" (%d,%d)",arr[j].l,arr[j].r);
printf("\n");
}
}
void Build()
{
e=st=0;des=n+cnt+1;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
AddEdge(st,i,monk[i].v);
for(int i=1;i<cnt;i++)
AddEdge(n+i,des,m*(t[i]-t[i-1]));
for(int i=1;i<=n;i++)
for(int j=1;j<cnt;j++)
if(monk[i].l<=t[j-1]&&monk[i].r>=t[j])
AddEdge(i,j+n,t[j]-t[j-1]);
}
int main()
{
int cas=1;
while(scanf("%d",&n)&&n)
{
cnt=0;
scanf("%d",&m);
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&monk[i].v,&monk[i].l,&monk[i].r);
t[cnt++]=monk[i].l;
t[cnt++]=monk[i].r;
sum+=monk[i].v;
}
sort(t,t+cnt);
cnt=unique(t,t+cnt)-t;
printf("Case %d: ",cas++);
Build();
solve(sum);
}
return 0;
}