题意:一个演员,给你N部电影,每部电影必须在M周前完成,每部电影一周有固定的拍摄时间,这个演员一天只能拍一部,问这个演员能否拍所有的电影。
思路:这题可以用二分匹配,匈牙利算法搞,应该很快,我用了网络流,熟练一下模板。
建图方法。
S - MOVIE ,权值是电影的拍摄次数。
MOVIE - 天数 ,将MOVIE和能拍摄的天数连起来,权值是1。
天数 - T ,将所有天数和T连起来,权值是1,因为每天最多拍摄一次。
这题WA了2次。原因是把Yes打成YES了,而且我居然花了半小时才DEBUG出来。。。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
#define Max 2005
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 1 << 30
int S,T ;
int Map[505][505] ;//把邻接表换成邻接矩阵了
int deep[Max] ;
int qe[Max * 100] ;
int dinic_bfs()
{
mem(deep,-1) ;
deep[S] = 0 ;
int h = 0 ,t = 0 ;
qe[h ++ ] = S ;
while(h > t)
{
int tt = qe[t ++ ] ;
for (int i = S ; i <= T ; i ++)
{
if(Map[tt][i] && deep[i] == -1)
{
deep[i] = deep[tt] + 1 ;
qe[h ++ ] = i ;
}
}
}
return deep[T] != -1 ;
}
int dinic_dfs(int now ,int f)
{
if(now == T)return f ;
int flow = 0 ;
for (int i = S ; i <= T ; i ++)
{
if(deep[i] == deep[now] + 1 && Map[now][i])
{
int mm = min(Map[now][i],f - flow) ;
int nn = dinic_dfs(i , mm) ;
flow += nn ;
Map[now][i] -= nn ;
Map[i][now] += nn ;
}
}
if(!flow )deep[now] = -2 ;
return flow ;
}
int dinic()
{
int flow = 0 ;
while(dinic_bfs())
{
flow += dinic_dfs(S,inf) ;
}
return flow ;
}
bool vis[10] ;
int main()
{
int t ;
cin >> t ;
while( t -- )
{
int n ;
cin >> n ;
mem(Map,0) ;
S = 0 ;T = 500 ;
int sum = 0 ;
for (int i = 1 ; i <= n ; i ++ )
{
mem(vis,0) ;
for (int j = 1 ; j <= 7 ; j ++ )cin >> vis[j] ;
int day ,week ;
cin >> day >> week ;
Map[S][i] = day ;//源点和电影连接
sum += day ;
for (int j = 0 ; j < week ; j ++ )
{
for (int k = 1 ; k <= 7 ; k ++ )
{
int dd = n + k + (j ) * 7 ;
Map[dd][T] = 1 ;//天数和汇点连接
if(vis[k])
{
Map[i][dd] = 1 ;//电影和该电影能拍的天数连接
}
}
}
}
int ans = dinic() ;
if(ans == sum)cout <<"Yes"<<endl;
else cout <<"No"<<endl;
}
return 0 ;
}