#71-【Dinic】奶牛食品

版权声明:反正也没有人会转,下一个 https://blog.csdn.net/drtlstf/article/details/82155412

Description

FJ的奶牛们只吃各自喜欢的一些特定的食物和饮料,除此之外的其他食物和饮料一概不吃。某天FJ为奶牛们精心准备了一顿美妙的饭食,但在之前忘记检查奶牛们的菜单,这样显然是不能不能满足所有奶牛的要求。但是FJ又不愿意为此重新来做,所以他他还是想让尽可能多的牛吃到他们喜欢的食品和饮料。

FJ提供了F (编号为1、2、…、F)种食品并准备了D (编号为1、2、…、D)种饮料, 他的N头牛(编号为1、2、…、N)都已决定了是否愿意吃某种食物和喝某种饮料。FJ想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料。

每一种食物和饮料只能由一头牛来用。例如如果食物2被一头牛吃掉了,没有别的牛能吃到食物2。

输入第一行包含三个用空格分开的整数N,F和D;接下来的N行描述每个奶牛的信息:第i+1行的前两个整数为F_i和D_i,接下来的F_i个整数表示奶牛i喜欢的食品编号,再接下来的D_i个整数表示奶牛i喜欢的饮料编号。

输出仅一行一个整数,表示FJ最多能让多少头奶牛吃到自己喜欢的食品和饮料。

样例

Dining.in

Dining.out

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

3

 

样例说明

输入数据表明:奶牛1喜欢的食物1、2;喜欢喝饮料3、1;奶牛2喜欢的食物2、3;喜欢喝饮料1、2;奶牛3喜欢的食物1、3;喜欢喝饮料1、2;奶牛4喜欢的食物1、3;喜欢喝饮料3;

那么下面的分配方法将是最优的:奶牛1不给食品和饮料;奶牛2分配食物2和饮料2;奶牛3分配食物1和饮料2;奶牛4分配食物3和饮料3。

【数据范围】

1<=F<=100,1<=D<=100,1<=N<=100

 

建图有点麻烦,其它照常。

#include <iostream>
#include <queue>
#include <cstring>

#define SIZE 5010
#define INF 1e+09

using namespace std;

struct edge
{
	int to, cap, reverse;
};

vector<edge> graph[SIZE];
int depth[SIZE], sink;

bool bfs(int start)
{
	int i, u, v;
	queue<int> q;
	
	memset(depth, -1, sizeof (depth));
	depth[start] = 0;
	q.push(start);
	while (!q.empty())
	{
		u = q.front();
		q.pop();
		if (u == sink)
		{
			return true;
		}
		for (i = 0; i < graph[u].size(); ++i)
		{
			v = graph[u][i].to;
			if ((depth[v] == -1) && (graph[u][i].cap > 0))
			{
				depth[v] = depth[u] + 1;
				q.push(v);
			}
		}
	}
	
	return false;
}

int dfs(int u, int flow)
{
	int i, v, ret = 0, delta;
	
	if (u == sink)
	{
		return flow;
	}
	for (i = 0; i < graph[u].size(); ++i)
	{
		edge &temp = graph[u][i];
		v = temp.to;
		if ((temp.cap > 0) && (depth[v] == depth[u] + 1))
		{
			delta = dfs(v, min(flow - ret, temp.cap));
			if (delta > 0)
			{
				ret += delta;
				temp.cap -= delta;
				graph[v][temp.reverse].cap += delta;
			}
			if (ret == flow)
			{
				return ret;
			}
		}
	}
	
	return ret;
}

int dinic(int start) // Dinic算法模板
{
	int maxflow = 0, delta;
	
	while (bfs(start))
	{
		delta = dfs(start, INF);
		if (!delta)
		{
			break;
		}
		maxflow += delta;
	}
	
	return maxflow;
}

void addedge(int u, int v, int cap)
{
	graph[u].push_back({v, cap, graph[v].size()});
	graph[v].push_back({u, 0, graph[u].size() - 1});
	
	return;
}

int main(int argc, char** argv)
{
	int n, f, d, count, count2, x, i;
	
	scanf("%d%d%d", &n, &f, &d);
	for (i = 1; i <= n; ++i) // 见图
	{
		addedge(f + i, f + n + i, 1); // 容量限制
		scanf("%d%d", &count, &count2);
		while (count--)
		{
			scanf("%d", &x);
			addedge(x, f + i, 1); // 食物→奶牛
		}
		while (count2--)
		{
			scanf("%d", &x);
			addedge(f + n + i, f + n + n + x, 1); // 奶牛→饮料
		}
	}
	
	sink = f + n + n + d + 1;
	for (i = 1; i <= f; ++i)
	{
		addedge(0, i, 1); // 源点→食物
	}
	for (i = 1; i <= d; ++i)
	{
		addedge(f + n + n + i, sink, 1); // 饮料→汇点
	}
	
	printf("%d", dinic(0));
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/drtlstf/article/details/82155412
71