poj 1698 二部图多重最大匹配(拍电影)

题意:某演员想拍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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值