题意:某演员想拍n部电影,每部电影有拍摄完毕的截止时间,以周为单位,而且每周只有给定的时间可以拍。另外每部电影有需要拍摄的天数。问此人能不能不耽误所有电影。
思路:二部图多重最大匹配。将电影作为X部,每天作为Y部(Y部最多有50*7=350个点),若电影i可以在第j天拍摄就置c[i][j]为1。每个X部点的约束值为该电影总共要拍摄的天数(即源点与X部点的权值),每个Y部点的约束值为1,求此二部图的多重最大匹配。若求得的最大流为所有电影需要拍摄的天数之和则输出Yes,否则输出No。
#include <stdio.h> #include <string.h> #define max(a,b) a>b?a:b #define min(a,b) a<b?a:b #define N 20+50*7+5 #define INF 0x3fffffff int n,m,T,sum; int f[N][N],c[N][N],p[N],a[N],q[N]; int temp[10]; void init(){ m = sum = 0; memset(c,0,sizeof(c)); memset(f,0,sizeof(f)); } int maxflow(int s,int t){ int i,front,rear,now,res=0; while(1){ front = rear = -1; memset(a,0,sizeof(a)); memset(p,0,sizeof(p)); q[++rear] = s; a[s] = INF; while(front < rear){ now = q[++front]; for(i = 0;i<=m;i++) if(!a[i] && c[now][i]-f[now][i]>0){ p[i] = now; a[i] = min(a[now],c[now][i]-f[now][i]); q[++rear] = i; } } if(!a[t]) break; for(i = t;i!=s;i=p[i]){ f[p[i]][i] += a[t]; f[i][p[i]] -= a[t]; } res += a[t]; } return res; } int main(){ freopen("a.txt","r",stdin); scanf("%d",&T); while(T--){ int i,j,k; init(); scanf("%d",&n); for(i = 1;i<=n;i++){ for(j = 1;j<=9;j++)//逐周读入数据 scanf("%d",&temp[j]); c[0][i] = temp[8];//通往源点的边 m = max(m,temp[9]);//为求图的最大顶点序号 sum += temp[8];//求最大流量 for(j = 1;j<=7;j++) if(temp[j]) for(k = 0;k<temp[9];k++) c[i][n+k*7+j] = 1; } m = n+7*m+1; for(i = n+1;i<m;i++)//通往汇点的边 c[i][m] = 1; printf("%s\n",maxflow(0,m)==sum?"Yes":"No"); } return 0; }