构图:
最多50周,350天
源点到每一天连一条容量为1的边,对于每个电影,可以拍摄的那些天连一条容量为1的边到这个电影,每个电影连一条容量为需求总天数的边到汇点。
看最大流是不是等于所有电影的需求总天数的和。
点数为天数+电影数+2。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #include <vector> #include <queue> #define maxn 500 #define maxm 1000 #define INF 10000000 int N,M,s,t; struct Edge{ int from,to,cap,flow; Edge(){} Edge(int s,int t,int c,int f):from(s),to(t),cap(c),flow(f){} }; vector <Edge> edges; vector <int> G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn]; struct film{ int s[8]; int D,W; }F[21]; void init(){ edges.clear(); for(int i=0;i<=N;i++){ G[i].clear(); } } void addedge(int from,int to,int cap){ edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); M=edges.size(); G[from].push_back(M-2); G[to].push_back(M-1); } bool bfs(){ memset(vis,0,sizeof(vis)); queue<int> Q; Q.push(s); d[s]=0; vis[s]=1; while(!Q.empty()){ int x=Q.front();Q.pop(); for(int i=0;i<G[x].size();i++){ Edge &e=edges[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow){ vis[e.to]=1; d[e.to]=d[x]+1; Q.push(e.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<G[x].size();i++){ Edge &e=edges[G[x][i]]; if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){ e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0) break; } } return flow; } int Maxflow(){ int flow=0; while(bfs()){ memset(cur,0,sizeof(cur)); flow+=dfs(s,INF); } return flow; } int main(){ int T; scanf("%d",&T); while(T--){ int nm; scanf("%d",&nm); int Maxw=0; for(int i=0;i<nm;i++){ for(int j=1;j<=7;j++){ scanf("%d",&F[i].s[j]); } scanf("%d%d",&F[i].D,&F[i].W); Maxw=max(Maxw,F[i].W); } N=Maxw*7+nm+1; init(); for(int i=1;i<=Maxw*7;i++){ addedge(0,i,1); } int tot=0; for(int i=0;i<nm;i++){ int cur=Maxw*7+i+1; for(int j=1;j<=7;j++){ if(F[i].s[j]){ for(int k=0;k<F[i].W;k++){ addedge(k*7+j,cur,1); } } } addedge(cur,N,F[i].D); tot+=F[i].D; } s=0;t=N; if(tot==Maxflow()){ printf("Yes\n"); } else printf("No\n"); } return 0; }