2018icpc Nanjing I. Magic Potion(gym101981) [二分图]

题目:

给n(heroes) m(monsters) k(magic)

下面n行给出每个英雄可以杀q种小怪兽and这些怪兽的编号

每个英雄只能杀一只怪兽 魔法药水可以使英雄再杀一怪兽 一个英雄最多使用一瓶magic

思路一(二分图匹配):

先对不使用magic的情况跑一遍匈牙利->返回有多少个hero能杀得到monster(代码中的Q)

这时from数组中已经存下每个 from[monster] = which hero 此时再跑一遍匈牙利 返回->剩下的hero在使用magic情况下还能再kill monster ->正好符合 per hero can only one magic!   二分图匹配,恐怖如斯!(最近看斗罗大陆的动漫 弹幕被"“恐怖如斯”刷屏,我也继承了哈哈哈)

注意QQ = min(k,还能继续kill的hero);

ans = Q + QQ;

AC代码(二分图)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
const int MaxN = 505;

int n,m,k;
vector<int> G[MaxN];
bool used[MaxN];
int Size[MaxN],from[MaxN];

bool match(int x){
	for(int i = 0;i < Size[x]; i++){
		if(!used[G[x][i]]){
			used[G[x][i]] = 1;
			if(from[G[x][i]] == -1 || match(from[G[x][i]])){
				from[G[x][i]] = x;
				return 1;
			}
		}
	}
	return 0;
}

int hungry(){
	int tot = 0;
	for(int i = 1;i <= n; i++) Size[i] = G[i].size();
	for(int i = 1;i <= n; i++){
		for(int j = 1;j <= m; j++) used[j] = 0;
		if(match(i)) ++tot;
	}
	return tot;
}

int main()
{
	scanf("%d %d %d",&n,&m,&k);
	for(int i = 1;i <= n; i++){
		int q;
		scanf("%d",&q);
		for(int j = 1;j <= q; j++){
			int cur;
			scanf("%d",&cur);
			G[i].push_back(cur);
		}
	}
	for(int i = 1;i <= m; i++) from[i] = -1;
	int Q = hungry();
	int QQ = hungry();
	printf("%d\n", Q + min(QQ, k));
}
发布了31 篇原创文章 · 获赞 5 · 访问量 1373

猜你喜欢

转载自blog.csdn.net/qq_43685900/article/details/102171853