输入格式
输出格式
输入输出样例
输入 #1复制
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
输出 #1复制
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)
除了附加源点和汇点之外,1到N点为N个猴子,其余编号为N+i的点代表区间[i,i+1]
对每个猴子,向区间[a,b]中的每个子区间连边,容量为1,表示该猴子在这个时间段喝水,并从源点向该猴子连边,容量为v,表示该猴子一共需要喝v单位水,这样进入每个猴子的流量为v,一共会流向v个小区间
对每个子区间[i,i+1],向汇点连边,容量为m,这限制了该时间段喝水的猴子数,因为最多只能有m个猴子在此时喝水,所以从该区间流出的流向也不能大于m
求最大流,如果最大流恰好等于每个猴子的需求量的总和,那么所有猴子都喝到了足够的水,否则一定有猴子没有被满足
输出方案时,我将每个猴子喝水的时间段存起来,然后统计连续的区间并输出
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
struct edge
{
int to,cap,flow;
};
vector<edge>e;
vector<int>v[50110];
vector<int>drink[110];
vector<pair<int,int> >ans[110];
int n,m,sum;
int s,t,maxflow,d[50110],kase,cnt;
int cur[50010];
bool vis[50110],use[50010];
void read(int& x)
{
char c=getchar();
x=0;
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
}
void link(int from,int to,int cap)
{
e.push_back((edge){to,cap,0});
e.push_back((edge){from,0,0});
cnt=e.size();
v[from].push_back(cnt-2);
v[to].push_back(cnt-1);
}
bool bfs()
{
queue<int>q;
memset(vis,0,sizeof(vis));
memset(d,INF,sizeof(d));
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty())
{
int fa=q.front();
q.pop();
for(int i=0;i<v[fa].size();i++)
{
edge& ed=e[v[fa][i]];
if(!vis[ed.to]&&ed.cap>ed.flow)
{
d[ed.to]=d[fa]+1;
vis[ed.to]=1;
q.push(ed.to);
}
}
}
return vis[t];
}
int dfs(int x,int a)
{
if(x==t||a==0)return a;
int flow=0,f;
for(int& i=cur[x];i<v[x].size();i++)
{
edge& ed=e[v[x][i]];
if(d[ed.to]==d[x]+1&&(f=dfs(ed.to,min(a,ed.cap-ed.flow)))>0)
{
flow+=f;
ed.flow+=f;
e[v[x][i]^1].flow-=f;
a-=f;
if(a==0)break;
}
}
return flow;
}
int main()
{
while(1)
{
read(n);
if(!n)return 0;
read(m);
memset(use,0,sizeof(use));
maxflow=0;sum=0;
s=0;
t=n+50001;
v[s].clear();
v[t].clear();
e.clear();
for(int i=1;i<=n;i++)
{
int a,b,c;
read(a);
read(b);
read(c);
sum+=a;
v[i].clear();
link(s,i,a);
for(int j=b;j<c;j++)
{
if(!use[j])
{
v[n+j].clear();
link(n+j,t,m);
use[j]=1;
}
link(i,n+j,1);
}
}
while(bfs())
{
memset(cur,0,sizeof(cur));
maxflow+=dfs(s,INF);
}
printf("Case %d: ",++kase);
if(maxflow<sum)
{
printf("No\n");
continue;
}
else printf("Yes\n");
for(int i=1;i<=n;i++)
{
drink[i].clear();
for(int j=0;j<v[i].size();j++)
{
edge ed=e[v[i][j]];
if(ed.cap==ed.flow&&ed.to!=s)drink[i].push_back(ed.to);
}
}
for(int i=1;i<=n;i++)
{
ans[i].clear();
int times=0,pos=drink[i][0];
sort(drink[i].begin(),drink[i].end());
drink[i].push_back(INF);
for(int j=0;j<drink[i].size();j++)
{
if(drink[i][j]+1!=drink[i][j+1])
{
ans[i].push_back(make_pair(pos,drink[i][j]+1));
pos=drink[i][j+1];
times++;
}
}
printf("%d",--times);
for(int j=0;j<ans[i].size()-1;j++)
{
printf(" (%d,%d)",ans[i][j].first-n,ans[i][j].second-n);
}
putchar('\n');
}
}
}