void-man

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

给出牛,饮料还有食物的数量,每头牛给出喜欢的饮料和食物,最后求出能够满足的牛的数量

看别人的算法,把牛分解成两个点,然后按照 饮料-牛1-牛1-食物的对应关系进行计算最大网络流,这样形成了多源点多汇点的最大流

如果这个点不分解的话,为什么不行?纠结...

后来想明白了,如果不把牛拆开的话,多个饮料会对应到一头牛上,并且这头牛如果再对应到另外的食物的话,也可算是增广路,但是已经不符合条件了

所以把牛拆开加一条1的路,可以限制每头牛只能对应一个饮料

先放上代码,回头思考

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string.h>
#include <queue>
#include <limits.h>
#define MAX 500
using namespace std;
int n,f,d;
int cap[MAX][MAX];
int EKarp(int s,int t)
{
	queue<int> Q;
	int a[MAX],flow[MAX][MAX],pre[MAX];
	int f = 0,u,v;
	memset(flow,0,sizeof(flow));
	while(1)
	{
		memset(a,0,sizeof(a));
		a[s] = INT_MAX;
		Q.push(s);
		while( !Q.empty() )
		{
			u = Q.front();
			Q.pop();
			for(v=s; v<=t; v++)
				if( !a[v] && cap[u][v] > flow[u][v] )
				{
					Q.push(v);
					a[v] = a[u] < cap[u][v] - flow[u][v] ? a[u] : cap[u][v] - flow[u][v];
					pre[v] = u;
				}
		}
		if( a[t] == 0 )
			break;
		for(u=t; u!=s; u=pre[u])
		{
			flow[pre[u]][u] += a[t];
			flow[u][pre[u]] -= a[t];
		}
		f += a[t];
	}
	return f;
}
int main()
{
	int ff,dd,ans,i;
	int food,drink;
	while( scanf("%d%d%d",&n,&f,&d) != EOF )
	{
		memset(cap,0,sizeof(cap));
		for(i=1; i<=n; i++)
		{
			scanf("%d%d",&ff,&dd);
			cap[i][i+n] = 1;
			while( ff-- )
			{
				scanf("%d",&food);
				cap[2*n+food][i] = 1;
			}
			while( dd-- )
			{
				scanf("%d",&drink);
				cap[i+n][2*n+f+drink] = 1;
			}
		}
		for(i=2*n+1; i<=2*n+f; i++)
			cap[0][i] = 1;
		for(i=2*n+f+1; i<=2*n+f+d; i++)
			cap[i][2*n+f+d+1] = 1;			
		ans = EKarp(0,2*n+f+d+1);
		printf("%d\n",ans);
	}
return 0;
}
posted on 2011-05-16 13:45  void-man  阅读(663)  评论(0)    收藏  举报