POJ_3281_Dining && NYOJ _326_Dining

Dining

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 13314 Accepted: 6092

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

Hint

One way to satisfy three cows is:

Cow 1: no meal

Cow 2: Food #2, Drink #2

Cow 3: Food #1, Drink #1

Cow 4: Food #3, Drink #3

The pigeon-hole principle tells us we can do no better since there are only three kinds of food or drink. Other test data sets are more challenging, of course.

题意

N头牛,F种食物 , D种饮料,每种食物和饮料数量都是1.每头牛都有自己喜欢的食物和饮料,

怎么分配食物和饮料才能使得尽量多的牛都能得到自己喜欢的?

建图:

边的方向:源点->食物->左牛->右牛->饮料->汇点。 容量为 1

我们把食物所对应的牛和饮料所对应的牛拆成两个顶点,之间连一条容量为1 的边,就保证了一头牛不会被分配多组食物和饮料。所以,直接计算最大流,就是答案。

源点  s --> 0;

food --> (1,F)

左牛 --> (F+1,F+N)

右牛 (F+N+1,F+N+N)

drink --> (F+N+N+1,F+N+N+D)

汇点  t = F+N+N+D+1

建完图,直接套 挑战上 模板

#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <algorithm>
#define Max_N 1005
#define inf 0x3f3f3f3f
using namespace std;

//用于表示结构体,终点,容量,反向边
struct edge{ int to, cap ,rev; };
vector<edge> G[Max_N];     //图的邻接表表示
int level[Max_N];          //顶点到源点的距离标号
int iter[Max_N];           //当前弧,在其之前的边已经没有用了
int N,F,D;

//向图中增加一条从from到to的容量为cap的边
void add_edge(int from, int to, int cap)
{
	G[from].push_back((edge) { to, cap, G[to].size() } );
	G[to].push_back((edge) { from, 0, G[from].size() - 1 } );
}

//通过bfs计算从源点出发的距离标号
void bfs(int s)
{
	memset(level,-1,sizeof(level));
	queue<int> Q;
	level[s] = 0;
	Q.push(s);
	while(!Q.empty())
	{
		int i;
		int v = Q.front(); Q.pop();
		for(i=0;i<G[v].size();i++)
		{
			edge &e = G[v][i];
			if(e.cap>0 && level[e.to]<0)
			{
				level[e.to] = level[v] + 1;
				Q.push(e.to);
			}
		}
	}
}

//通DFS寻找增广路
int dfs(int v,int t,int f)
{
	if(v==t)
	{
		return f;
	}
	for(int &i = iter[v];i<G[v].size();i++)
	{
		edge &e = G[v][i];
		if(e.cap > 0 && level[v] < level[e.to])
		{
			int d = dfs(e.to,t,min(f,e.cap));
			if(d>0)
			{
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
} 

//求解s到t的最大流
int max_flow(int s,int t)
{
	int flow = 0;
	while(1)
	{
		bfs(s);
		if(level[t]<0)
		{
			return flow;
		}
		memset(iter,0,sizeof(iter));
		int f;
		while((f = dfs(s, t, inf)) >0 )
		{
			flow += f;
		}
	}
} 

int main()
{
    while(scanf("%d%d%d",&N,&F,&D)!=EOF)
    {
        int i,j;
        int food,drink,v;
        for(i=0;i<Max_N;i++)
        {
        	G[i].clear();
        }
        for(i=1;i<=N;i++)
        {
            scanf("%d%d",&food,&drink);
            for(j=1;j<=food;j++)
            {
                scanf("%d",&v);
                add_edge(v,F+i,1);//食物和左边的牛 连一条 边
            }
            for(j=1;j<=drink;j++)
            {
                scanf("%d",&v);
                add_edge(F+N+i,F+N+N+v,1);//右边的牛 和饮料连一条 边
            }
        }
		int s = 0,t = N+N+F+D+1;//超源,超汇
        for(i=1;i<=F;i++)
        {
			add_edge(s,i,1); //源点 和所有 的食物连一条边
		}
		for(i=1;i<=N;i++)
		{
			add_edge(F+i,F+N+i,1);//左边的牛 和 右边的牛连一条 边
		}
        for(i=1;i<=D;i++)
        {
			add_edge(F+N+N+i,t,1);//所有的饮料和 汇点连一条边
		}
        printf("%d\n",max_flow(s,t));
    }
    return 0;
}
时间: 2024-10-13 00:30:23

POJ_3281_Dining && NYOJ _326_Dining的相关文章

NYOJ 237 游戏高手的烦恼 &amp;&amp; POJ3041-Asteroids ( 二分图的最大匹配 )

链接: NYOJ 237  游戏高手的烦恼:click here~~ POJ  3041 Asteroids           :click here~~ 题意: 两题一样,翻译不同而已. 有一位传说级游戏高手,在闲暇时间里玩起了一个小游戏,游戏中,一个n*n的方块形区域里有许多敌人,玩家可以使用炸弹炸掉某一行或者某一列的所有敌人.他是种玩什么游戏都想玩得很优秀的人,所以,他决定,使用尽可能少的炸弹炸掉所有的敌人. 现在给你一个游戏的状态,请你帮助他判断最少需要多少个炸弹才能炸掉所有的敌人吧.

NYOJ 49 开心的小明

开心的小明 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 小明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:"你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N 元钱就行".今天一早小明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N 元.于是,他把每件物品规定了一个重要度,分为5 等:用整数1~5 表示,第5 等最重要.他还从因特网上查到了每件物品的价格(都是整数元).

NYOJ 106 背包问题

背包问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1<=v,w<=10):如果给你一个背包它能容纳的重量为m(10<=m<=20),你所要做的就是把物品装到背包里,使背包里的物品的价值总和最大. 输入 第一行输入一个正整数n(1<=n<=5),表示有n组测试数据: 随后有n测试数据,每组测试数据的第一行有两个正整数s,m(1<=s<=10

NYOJ 289 苹果

苹果 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 ctest有n个苹果,要将它放入容量为v的背包.给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值. 输入 有多组测试数据,每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v,n.v同时为0时结束测试,此时不输出.接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w.所有输入数字的范围大于等于0,小于等于1000. 输出 对每组测试数据输出一个整数,代表能放入背包的苹

nyoj 括号匹配

这个方程有两种形式,本文采用 if(s[i]=s[j]) dp[i][j]=d[i-1][j-1] dp[i][j]=min(dp[i][k]+dp[k+1][j],dp[i][j]) (i=<k<j) 其实与另一种方法比较:根据j的所有匹配情况取最小值 1.i到j无匹配,取为dp[i][j-1]+1 2.列举所有匹配情况 dp[i][k-1]+dp[k+1][j] 取上述所有情况最小值 两者都能获得正确的结果. 同时两者的初始化为 dp[i][j]==1 if(i==j) 规划方向为:  

NYOJ 461-Fibonacci数列(四)(求斐波那契数列前4位)

题目地址:NYOJ 461 思路:斐波那契数列的通项公式为 然后下一步考虑如何产生前4位: 先看对数的性质,loga(b^c)=c*loga(b),loga(b*c)=loga(b)+loga(c);假设给出一个数10234432, 那么log10(10234432)=log10(1.0234432*10^7)[用科学记数法表示这个数]=log10(1.0234432)+7; log10(1.0234432)就是log10(10234432)的小数部分. log10(1.0234432)=0.0

NYOJ 527 AC_mm玩dota

AC_mm玩dota 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 大家都知道AC_mm比较喜欢玩游戏,特别是擅长war3这款经典游戏.某天AC_mm来到了VS平台上 ,准备去虐菜鸟,正巧一个不小心将我们ACM队长虐了 ^_^,我们的队长这下可不高兴了,说要出一道难题让AC_mm难堪一下.题目描述是这样的,给一个正整数n,n在二进制表示的情况下(不含前导0和符号位)有a个1和b个0,求斐波拉契数列的第a*b项对1314520取模后的值ans. 注意(斐波拉契数列:

NYOJ 832 合并游戏

合并游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 大家都知道Yougth除了热爱编程之外,他还有一个爱好就是喜欢玩.某天在河边玩耍的时候,他发现了一种神奇的石子,当把两个石子放在一起的时候,后一个石子会消失,而且会蹦出一定数量的金币,这可乐坏了Yougth,但是他想得到最多的金币,他该怎么做? 输入 首先一行,一个n(1<=n<=10),表示有n个石子.接下来n*n的一个矩阵,Aij表示第i个和第j个合并蹦出的金币值(小于10000,注意合并后j会消失).

nyoj 12 喷水装置(二)【贪心】+【区间完全覆盖覆盖】

题意:... 这道题就是区间问题三种中的区间完全覆盖问题,不懂的可以看我上一篇也是区间完全覆盖. 直接上代码: #include <stdio.h> #include <math.h> #include <algorithm> using std::sort; struct node{ double le, ri; }s[1005]; int cmp(node a, node b) { return a.le < b.le; } int main() { int