这个题白书上的,确实比较麻烦。想到网络流不难,但需要注意的是需要区间建图,也就类似于先要离散化,不能以它给的每个时间点作为结点建图,否则超时。
需要注意的地方如下:
1、建图按区间进行建图。
2、因为建图按区间建的,所以后面输出答案的时候就比较麻烦,题目中存在可以同时让几个喝水的情况,那么就需要记录当前状态有多少在喝水,类似于把它看做几个点考虑,一个用完了再用另外一个,具体可以看代码中的 hasuse数组。
3、输出的时候需要合并相邻区间,也就是说能合并的就合并
代码:
#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;
}