POJ-3281(Dining)

Description

Cows are such finicky eaters. Each cow has a preference for certain foods and drinks, and she will consume no others.

Farmer John has cooked fabulous meals for his cows, but he forgot to check his menu against their preferences. Although he might not be able to stuff everybody, he wants to give a complete meal of both food and drink to as many cows as possible.

Farmer John has cooked F (1 ≤ F ≤ 100) types of foods and prepared D (1 ≤ D ≤ 100) types of drinks. Each of his N (1 ≤ N ≤ 100) cows has decided whether she is willing to eat a particular food or drink a particular drink. Farmer John must assign a food type and a drink type to each cow to maximize the number of cows who get both.

Each dish or drink can only be consumed by one cow (i.e., once food type 2 is assigned to a cow, no other cow can be assigned food type 2).

Input

Line 1: Three space-separated integers: N, F, and D
Lines 2…N+1: Each line i starts with a two integers Fi and Di, the number of dishes that cow i likes and the number of drinks that cow i likes. The next Fi integers denote the dishes that cow i will eat, and the Di integers following that denote the drinks that cow i will drink.

Output

Line 1: A single integer that is the maximum number of cows that can be fed both food and drink that conform to their wishes

Sample Input
4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3

Sample Output
3

思路
很好的一道建模题,建立好模型,很容易发现这是一道最大流的题目。
然后运用EK算法即可解题.

AC代码

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
const int INF=0x7fffffff;
const int maxn=2000+5;
int n,m,d;
int vis[maxn],liu[maxn][maxn],p[maxn];
int EK_BFS(int start,int end)
{
	queue<int>q;//不用全局 ,省去清空队列的麻烦 
	memset(vis,0,sizeof(vis));
	memset(p,-1,sizeof(p));
	q.push(start);
	vis[start]=1;
	while(q.size()){
		int t=q.front();
		q.pop();
		if(t==end)
			return 1;//到达汇点 
		for(int i=0;i<=4*(n+m+d);i++){//寻找增广路径 
			if(liu[t][i]!=0&&!vis[i]){ //存在这样的路径并且没有走过 
				vis[i]=1;
				p[i]=t;//记录增广路径 
				q.push(i);
			}
		}
	}
	return 0;//残留图中不再存在增广路径 
}
int EK_network(int start,int end)
{
	int ans=0;
	while(EK_BFS(start,end)){
		int u=end;//利用前驱寻找路径 
		int temp=INF;
		while(p[u]!=-1){
			temp=min(temp,liu[p[u]][u]);
			u=p[u];
		}
		u=end;
		ans+=temp;
		while(p[u]!=-1){
			liu[p[u]][u]-=temp;//改变正向边的容量 
			liu[u][p[u]]+=temp;//反向边,防止出现堵塞的情况
							   //改变反向边的容量 
			u=p[u]; 
		}
	}
	return ans;
}
int main()
{
	scanf("%d%d%d",&n,&m,&d);
		memset(liu,0,sizeof(liu));
		for(int i=1;i<=n;i++){
			int x,y;
			scanf("%d%d",&x,&y);
			while(x--){
				int a;
				scanf("%d",&a);
				liu[0][a]=1;
				liu[a][n+m+d+i]=1;
				liu[n+m+d+i][2*(n+m+d)+i]=1;	
			}
			while(y--){
				int a;
				scanf("%d",&a);
				liu[2*(n+m+d)+i][3*(n+m+d)+a]=1;
				liu[3*(n+m+d)+a][4*(n+m+d)]=1;	
			}
		}
		printf("%d\n",EK_network(0,4*(n+m+d)));
	
	return 0;
}
全部评论

相关推荐

10-29 16:42
门头沟学院 Java
1.今天什么国标的公司打电话约面试,还得准备ppt,好麻烦,网上查薪资一般,打算拒了,不面了2.字节又复活了,什么安全开发,也不知道怎么样,面一面试试吧,还是挺想去字节的,但好难,随缘吧所以今天没面试
嵌入式的小白:面试前可以好好准备下 1.看看你投递的岗位的岗位描述,分析下是哪个业务线,同使要罗列他们描述中提到的技术点 2.根据1中的两点准备 3.岗位描述中应该还有语言要求,这个刷刷八股,要是对自己语言能力很有把握,那就不用看这点了 4.找下你简历中项目部分,看有没有和岗位描述中技术点重合的,这种在面试提到项目时,是高概率问题 好好准备,祝你面试顺利
我的求职进度条
点赞 评论 收藏
分享
10-22 19:44
门头沟学院 Java
面了100年面试不知...:那我得去剪个头
点赞 评论 收藏
分享
千千倩倩:简历问题有点多,加v细聊
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务