2018ICPC南京 Problem I. Magic Potion(二分图最大匹配或网络最大流)

Problem I. Magic Potion

There are n heroes and m monsters living in an island. The monsters became very vicious these days, so the heroes decided to diminish the monsters in the island. However, the i-th hero can only kill one monster belonging to the set Mi . Joe, the strategist, has k bottles of magic potion, each of which can buff one hero’s power and let him be able to kill one more monster. Since the potion is very powerful, a hero can only take at most one bottle of potion.

Please help Joe find out the maximum number of monsters that can be killed by the heroes if he uses the optimal strategy.

Input

The first line contains three integers n, m, k (1 ≤ n, m, k ≤ 500) — the number of heroes, the number of monsters and the number of bottles of potion.

Each of the next n lines contains one integer ti , the size of Mi , and the following ti integers Mi,j (1 ≤ j ≤ ti), the indices (1-based) of monsters that can be killed by the i-th hero (1 ≤ ti ≤ m, 1 ≤ Mi,j ≤ m).

Output

Print the maximum number of monsters that can be killed by the heroes.

题意

有n个英雄,m个怪,一个英雄最多杀一个怪,但有k次机会可以让一个英雄多杀一个怪,但一个英雄最多也只能杀两个。

思路

首先我想到了二分图最大匹配(匈牙利算法),如果没有k那就是二分图匹配的模板题,多了个k就是网络最大流的板子题。但我觉得二分图最大匹配也能写,就稍微改变了匈牙利算法,最后也AC了。

二分图最大匹配的思路就是将所有英雄都复制一遍,这样就有2n个英雄,前n个英雄和后n个英雄是完全一样的。因为每个英雄都可以杀一个怪,所以前n个就直接跑最大,后n个是因为有额外k次机会,所以击杀上限为k。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+10;
int n,m,k,a[1005][505],b[505],girl[505];
bool find(int x){              //给英雄x匹配怪物
    int i,j;  
    for (j=1;j<=m;j++)
	{
        if (a[x][j]==1 && b[j]==0)        //如果可以匹配,并且没有被标记
        {  
            b[j]=1;  
            if (girl[j]==0 || find(girl[j])) {   
                girl[j]=x;  
                return true;  
            }  
        }  
    }
    return false;  
}
int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)        //输入并复制英雄
	{
		int s,x;
		cin>>s;
		for(int j=1;j<=s;j++)
		{
			scanf("%d",&x);
			a[i][x]=1;
			a[n+i][x]=1;
		}
	}
	int sum=0,sum1=0;
	for (int i=1;i<=2*n;i++)      //给每个英雄找匹配的怪
	{  
	    memset(b,0,sizeof(b));       //清除标记
	    if (find(i))                 //如果匹配到了
		{
			if(i<=n)
				sum++;
			else
				sum1++;
		}
		  
	}
	cout<<sum+min(sum1,k)<<endl;
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值