【题意】给你一个时限,一个工作的时间长度,和可以工作的日子(星期日到星期六),让你求出是否可以拍完所有的电影。
【题解】建图是关键,我们可以列出两列,第一列是不同的电影,第二列是星期的日子,然后开始连边。当然,这时我们发现会有一些不和谐,也就是说,因为每部电影的时限不同,所以有一部分(星期)只能拍某部电影,而其他的不行。所以,我想到了,将其分开,也就是个管个的——时限久的可以连上时限短的(星期),最后做一遍最大流就可以了。
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define inf 2147483641
using std::swap;
int tot,bg,ed,next[6000],to[6000],edge[6000],s[200],deep[165],g[165];
int f[21][7],d[21],point[21],w[21],pi,first[7],beh[165];
//排序,(选择) ;
inline void sort(int x)
{
for(int i=1;i<=x-1;i++)
{
int k=i;
for(int j=i+1;j<=x;j++)
if(w[point[j]]<w[point[k]])k=j;
if(k!=i)swap(point[k],point[i]);
}
}
//添边;
inline void add(int x,int y,int z)
{
edge[tot]=z;to[tot]=y;next[tot]=s[x];s[x]=tot++;
edge[tot]=0;to[tot]=x;next[tot]=s[y];s[y]=tot++;
}
//构建残量网络图;
inline bool bfs()
{
memset(deep,0,sizeof(deep));
deep[bg]=1;g[pi=1]=bg;
for(int fi=1;fi<=pi;fi++)
{
int IOI=g[fi];
for(int child=s[IOI];child;child=next[child])//child是枚举边;
if(edge[child]&&(!deep[to[child]]))
{
g[++pi]=to[child];deep[to[child]]=deep[IOI]+1;
}
}
return deep[ed];
}
int min(int x,int y){return x<y?x:y;}
inline int dfs(int x,int low)
{
int now=0;
if(x==ed)return low;
for(int i=s[x];i&&now<low;i=next[i])
if(edge[i]&&(deep[to[i]]==deep[x]+1))
{
int k=dfs(to[i],min(low-now,edge[i]));
edge[i]-=k;edge[i^1]+=k;
now+=k;
}
if(now==0)deep[x]=0;
return now;
}
int main()
{
int t,n;//t记录数据组数;
scanf("%d",&t);
for(;t;t--)
{
memset(s,0,sizeof(s));
scanf("%d",&n);
int ans=0,cont=0;//ans记录答案,cont记录流量流出的和;
tot=2;
for(int p=1;p<=n;p++)
{
for(int j=0;j<=6;j++)scanf("%d",&f[p][j]);
scanf("%d%d",&d[p],&w[p]);
cont+=d[p];
point[p]=p;
}
//建图;
for(int j=0;j<=6;j++)
{
first[j]=j+1;
beh[j+1]=0;
}
int l=7;//记录图中天数的节点数;
bg=1;ed=2;
//排序;
sort(n);
point[n+1]=0;
add(bg,3,d[point[1]]);
for(int j=0;j<=6;j++)
{
add(j+n+3,ed,w[point[1]]);
if(f[point[1]][j])add(3,j+3+n,inf);
}
for(int i=2;i<=n;i++)
{
add(bg,i+2,d[point[i]]);
for(int j=0;j<=6;j++)
{
if((w[point[i]]-w[point[i-1]])>0)
{
l++;
add(l+n+2,ed,w[point[i]]-w[point[i-1]]);
beh[l]=first[j];first[j]=l;
}
if(f[point[i]][j])
for(int k=first[j];k;k=beh[k])
add(i+2,k+n+2,inf);
}
}
while(bfs())ans+=dfs(bg,inf);
if(ans==cont)printf("Yes\n");
else printf("No\n");
}
return 0;
}