Problem I. Magic Potion

题意:有n个英雄,m个怪物,k瓶药水,每个英雄只能选择杀死自己能杀的怪物集合里的怪物,一个英雄能杀死一个怪物,但是如果一个英雄喝了一瓶药水之后,他能多杀一个怪物,一个英雄最多喝一瓶药水。问你这n个英雄最多能杀死多少只怪物。

思路:二分图的经典题,可以利用匈牙利算法解决。因为题目多了可以使用药水的条件,因此我们可以使用两次匈牙利算法来解决这道题,第一次匈牙利算法可以找出每个英雄在不使用药水的情况下最多杀死多少怪物(sum1),第二次匈牙利算法假设每个英雄都有使用一次药水的机会,看看他们又能杀死多少只怪物(sum2)。将sum2与k作比较,如果sum2>=k,那么ans=k+sum1,如果sum2<k,那么ans=sum2+sum1.

#include <cstring> 
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn=5100;

int h[maxn],e[maxn],ne[maxn],idx;
bool st[maxn];
int match[maxn];

void init()
{
	memset(h,-1,sizeof h);
	idx=0;
}

void add_to_head(int a,int b)
{
	e[idx]=b;
	ne[idx]=h[a];
	h[a]=idx;
	idx++;
}

bool find(int x)
{
	for(int i=h[x];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(!st[j])
		{
			st[j]=true;
			if(match[j]==0||find(match[j]))
			{
				match[j]=x;
				return true;
			}
		}
	}
	
	return false;
}
 
int main()
{
	init();
	int n,m,k;
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
	{
		int nn,x;
		scanf("%d",&nn);
		while(nn--) 
		{
			scanf("%d",&x);
			add_to_head(i,x);
		}
	}
	int sum1=0,sum2=0;
	for(int i=1;i<=n;i++)
	{
		memset(st,0,sizeof st);
		if(find(i)) sum1++;
	}
	for(int i=1;i<=n;i++)
	{
		memset(st,0,sizeof st);
		if(find(i)) sum2++;
	}
	if(sum2>=k) cout<<k+sum1;
	else cout<<sum1+sum2;
	
	return 0;
}

第三个数据点一直runtime error,检查不出来错误,后来发现是数组开小了,以为开到510就够了,没有认真分析题目。用邻接表来写匈牙利的时候,h[N]数组中的N表示点的个数,e[M],ne[M]表示边的个数,这个题目中其实只给了点的个数,边的个数是n*m,至少要2500个的。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值