【bzoj1854】[Scoi2010]游戏

1854: [Scoi2010]游戏

Time Limit: 5 Sec   Memory Limit: 162 MB
Submit: 5274   Solved: 2107
[ Submit][ Status][ Discuss]

Description

lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示。当他使用某种装备时,他只能使用该装备的某一个属性。并且每种装备最多只能使用一次。 游戏进行到最后,lxhgww遇到了终极boss,这个终极boss很奇怪,攻击他的装备所使用的属性值必须从1开始连续递增地攻击,才能对boss产生伤害。也就是说一开始的时候,lxhgww只能使用某个属性值为1的装备攻击boss,然后只能使用某个属性值为2的装备攻击boss,然后只能使用某个属性值为3的装备攻击boss……以此类推。 现在lxhgww想知道他最多能连续攻击boss多少次?

Input

输入的第一行是一个整数N,表示lxhgww拥有N种装备 接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值

Output

输出一行,包括1个数字,表示lxhgww最多能连续攻击的次数。

Sample Input

3
1 2
3 2
4 5

Sample Output

2

HINT

【数据范围】
对于30%的数据,保证N < =1000
对于100%的数据,保证N < =1000000

Source

[ Submit][ Status][ Discuss]



。。。二分图最大匹配


对于每一个武器,我们把他向两个属性连边。

显然成了一个二分图,然后跑一下匈牙利就好了


注:匈牙利的交替路标记要注意一下,就是因为复杂度关系不能用memset,那么我们考虑开一个类似垃圾回收的东西,把每次有标记的位置扔进去,然后直接重置这些有标记的位置就好了


PS.话说有memset的代码扔到luogu上是能过的,又是因为bzoj的老爷机吗233


代码:

#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<cstring>
#include<cmath>
using namespace std;

typedef long long LL;

const int INF = 2147483647;
const int maxm = 10010;
const int maxn = 1000010;

int n;
queue<int> Q;
vector<int> e[maxm];
int link[maxn];
bool vis[maxn];

inline LL getint()
{
	LL ret = 0,f = 1;
	char c = getchar();
	while (c < '0' || c > '9')
	{
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9')
		ret = ret * 10 + c - '0',c = getchar();
	return ret * f;
}

inline void clear()
{
	while (!Q.empty())
	{
		vis[Q.front()] = 0;
		Q.pop();
	}
}

inline bool hungary(int u)
{
	for (int i = 0; i < e[u].size(); i++)
	{
		int v = e[u][i];
		if (vis[v]) continue;
		vis[v] = 1;
		Q.push(v);
		if (!link[v] || hungary(link[v]))
		{
			link[v] = u;
			return 1;
		}
	}
	return 0;
}

int main()
{
	n = getint();
	for (int i = 1; i <= n; i++)
	{
		int u = getint(),v = getint();
		e[u].push_back(i);
		e[v].push_back(i);
	}
	int ans = 0;
	for (int i = 1; i <= 10000; i++)
	{
		clear();
		if (!hungary(i))
			break;
		ans++;
	}
	printf("%d",ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值