poj1149

EK模板,本题关键在于构图。

将顾客作为结点,构图如下:

1.取超级源点和超级汇点;

2.当猪圈被第一次打开时,在源点与当前顾客之间连接一条边,容量为该猪圈的猪的头数;

3.当某个猪圈 不是被第一次打开时,在上一个打开该猪圈的顾客与当前打开该猪圈的顾客之间连接一条边,容量为无穷大;

4.在每个顾客与源点之间连接一条边,容量为该顾客要买猪的头数。

代码如下:

//47ms
#include <iostream>
#include <queue>
using namespace std;

const int INF = 0x7fffffff;
const int mMax = 1005;
const int nMax = 105;

int cap[nMax][nMax], flow[nMax][nMax];
int pre[nMax], dist[nMax];

int min(int a, int b)
{
	return a > b ? b : a;
}
int Edmonds_Karp(int sta, int end)
{
	int i, curr, max = 0;
	
	memset(flow, 0, sizeof(flow));
	while(true)
	{
		memset(pre, 0, sizeof(pre));
		memset(dist, 0, sizeof(dist));
        queue<int> Q;
        Q.push(sta);
		dist[sta] = INF;
		pre[sta] = sta;
		while(!Q.empty())
		{
            curr = Q.front();
			Q.pop();
			for(i = 0; i <= end; i++)
				if(!dist[i] && flow[curr][i] < cap[curr][i])
				{
					dist[i] = min(dist[curr], cap[curr][i] - flow[curr][i]);
					pre[i] = curr;
					Q.push(i);
				}
        }
		
		if(dist[end] == 0)
			break;
		
		for(i = end; i != sta; i = pre[i])
		{
			curr = pre[i];
			flow[curr][i] += dist[end];
			flow[i][curr] -= dist[end];
		}
		max += dist[end];
	}
	return max;
}
int main()
{
	int m, n, k, i, j, key;
	int pighouse[mMax] = {0};
	int visit[mMax] = {0};
	
	//freopen("a.txt", "r", stdin);
	memset(cap, 0, sizeof(cap));
	cin >> m >> n; 
	for(i = 1; i <= m; i++)
		cin >> pighouse[i]; 
	for(i = 1; i <= n; i++)
	{
	   cin >> k; 
		 for(j = 1; j <= k; j++)
		 {
			cin >> key;
			if(!visit[key])
				cap[0][i] += pighouse[key];//因为顾客可以同时访问几个猪圈,所以源点与该顾客之间的边的容量等于所有这些猪圈的猪的和
 			else
				cap[visit[key]][i] = INF;
			visit[key] = i;
		 }
		 cin >> key;
         cap[i][n+1] = key;
	}
	cout << Edmonds_Karp(0, n+1) << endl;
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值