Description
As for a film,
- it will be made ONLY on some fixed days in a week, i.e., Alice can only work for the film on these days;
- Alice should work for it at least for specified number of days;
- the film MUST be finished before a prearranged deadline.
For example, assuming a film can be made only on Monday, Wednesday and Saturday; Alice should work for the film at least for 4 days; and it must be finished within 3 weeks. In this case she can work for the film on Monday of the first week, on Monday and Saturday of the second week, and on Monday of the third week.
Notice that on a single day Alice can work on at most ONE film.
Input
Output
Sample Input
2 2 0 1 0 1 0 1 0 9 3 0 1 1 1 0 0 0 6 4 2 0 1 0 1 0 1 0 9 4 0 1 1 1 0 0 0 6 2
Sample Output
Yes No
Hint
A proper schedule for the first test case: date Sun Mon Tue Wed Thu Fri Sat week1 film1 film2 film1 film1 week2 film1 film2 film1 film1 week3 film1 film2 film1 film1 week4 film2 film2 film2
//
个演员很想参加film,但是一天只能参加一项,且每项必须在规定的几个星期内参加规定的天数,求演员是否能全部完成所有的film档期。 可以考虑用网络流做,加源汇点,如果film_i 和week_i_day_j天有联系,那么就连一条INF边,源点到film_i连一条day_i边,各个星期的天数到汇点连一条1边,求最大流是否和总天数相等
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010;
const int M=50000;
const int inf=(1<<28);
int head[N];
struct Edge
{
int v,next,w;
} edge[M];
int cnt,n,s,t;//n从0开始 0->n-1
void addedge(int u,int v,int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].v=u;
edge[cnt].w=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
int sap()
{
int pre[N],cur[N],dis[N],gap[N];
int flow=0,aug=inf,u;
bool flag;
for(int i=0; i<n; i++)
{
cur[i]=head[i];
gap[i]=dis[i]=0;
}
gap[s]=n;
u=pre[s]=s;
while(dis[s]<n)
{
flag=0;
for(int &j=cur[u]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if(edge[j].w>0&&dis[u]==dis[v]+1)
{
flag=1;
if(edge[j].w<aug) aug=edge[j].w;
pre[v]=u;
u=v;
if(u==t)
{
flow+=aug;
while(u!=s)
{
u=pre[u];
edge[cur[u]].w-=aug;
edge[cur[u]^1].w+=aug;
}
aug=inf;
}
break;
}
}
if(flag) continue;
int mindis=n;
for(int j=head[u]; j!=-1; j=edge[j].next)
{
int v=edge[j].v;
if(edge[j].w>0&&dis[v]<mindis)
{
mindis=dis[v];
cur[u]=j;
}
}
if((--gap[dis[u]])==0)
break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return flow;
}
//初始化 cnt=0;memset(head,-1,sizeof(head));
int week[8],d[N],w[N];
int main()
{
int ci;scanf("%d",&ci);
while(ci--)
{
cnt=0;
memset(head,-1,sizeof(head));
int fin;scanf("%d",&fin);
int total=0;
int maxweek=0;
s=0;
for(int i=1;i<=fin;i++)
{
for(int j=0;j<7;j++)scanf("%d",&week[j]);
scanf("%d%d",&d[i],&w[i]);
maxweek=max(maxweek,w[i]);total+=d[i];
addedge(0,i,d[i]);
for(int j=0;j<w[i];j++)//枚举每一天
{
for(int k=0;k<7;k++)
{
if(week[k])
{
addedge(i,fin+j*7+k+1,inf);
}
}
}
}
n=fin+maxweek*7+2;
t=n-1;
for(int j=0;j<maxweek;j++)
{
for(int k=0;k<7;k++)
{
addedge(fin+j*7+k+1,t,1);
}
}
int ans=sap();
if(ans==total) printf("Yes\n");
else printf("No\n");
}
return 0;
}