题目链接

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

思路

参考:

http://hzwer.com/2950.html

http://blog.csdn.net/PoPoQQQ/article/details/41544997

法一:二分图最大匹配

思路同bzoj 1911.

将每种武器和它的两种属性连边,因为属性数为\(1e3\),武器数为\(1e6\),故用属性去匹配武器,这也符合属性从小到大连续的要求。

注意点,匈牙利算法中每次都要初始化\(used[]\)数组,在这里代价太高,故可用时间戳代替(一开始将时间戳开成了\(bool\)数组玄学到哭泣)。

法二:并查集

十分巧妙。

将武器的属性抽象成点,考虑在同一种武器的两种属性间连边。

如果一个联通块了呈树形结构,且树中节点为\(x\)个,则能从中取\(x-1\)个武器。

方式是每个点分配给它上面的那条边,这样,除了根节点之外的每个点都能分配到一条边。即这些\(x-1\)个属性都能对应到一个武器。

如果不是树形结构,且其中节点为\(x\)个,则能取\(x\)个武器。

因为不是树,所以其中必然有环。那么,给环上的每个点分配它顺时针方向的一条边,给不在环上的点分配靠近环方向的边。这样,每个点都能分配到一条边。即\(x\)个属性每个都能对应到一个武器。

可以考虑用并查集来做。祖先节点为编号最大的节点,其是否可以被选择不确定,其子孙节点都是可以选择的(详见上面讨论的两种情况)。

考虑在\(x\)和\(y\)之间加边,

如果\(x\)的祖先\(fx\)与\(y\)的祖先\(fy\)相同,则说明加出了环,则祖先节点本身也可被选择;

如果不同,则让两个祖先中较小的那个未被选择的能够被选择。

最后从小到大扫描一遍,不连续即停。

小结

两种不同的建图方式,两种做法,都很有启发意义。

Code

Ver. 1

#include <bits/stdc++.h>
#define maxn 10000
#define maxm 1000010
using namespace std;
typedef long long LL;
struct Edge {
int to, ne;
Edge(int _to=0, int _ne=0) : to(_to), ne(_ne) {}
}edge[maxm * 2];
int tot, ne[maxm], T, match[maxm], vis[maxm];
void add(int u, int v) {
edge[tot] = Edge(v, ne[u]);
ne[u] = tot++;
}
int find(int u) {
for (int i = ne[u]; ~i; i = edge[i].ne) {
int v = edge[i].to;
if (vis[v] != T) {
vis[v] = T;
if (!match[v] || find(match[v])) {
match[v] = u;
return true;
}
}
}
return false;
}
int main() {
int n;
scanf("%d", &n);
tot = 0; memset(ne, -1, sizeof(ne));
for (int i = 0; i < n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
add(x, i), add(y, i);
}
int i = 1;
for (; i <= maxn; ++i) {
++T;
if (!find(i)) break;
}
printf("%d\n", i-1);
return 0;
}

Ver. 2

#include <bits/stdc++.h>
#define maxn 10000
using namespace std;
typedef long long LL;
bool vis[maxn+10];
int fa[maxn+10];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= maxn; ++i) fa[i] = i;
for (int i = 0; i < n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
x = find(x), y = find(y);
if (x == y) vis[x] = true;
else {
if (x > y) swap(x, y);
if (vis[x]) vis[y] = true;
else vis[x] = true;
fa[x] = y;
}
}
int i=1;
for (; i <= maxn && vis[i]; ++i);
printf("%d\n", i-1);
return 0;
}

bzoj 1854 游戏 二分图匹配 || 并查集的更多相关文章

  1. BZOJ 1854 游戏(二分图匹配或并查集)

    此题的二分图匹配做法很容易想,就是把属性当做s集,武器当做t集,如果该武器拥有该武器则连一条边. 那么答案就是求该二分图的最大前i个匹配.将匈牙利算法改一改,当前找不到增广路就break. 但是过这个 ...

  2. HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流

    二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...

  3. BZOJ 1854: [Scoi2010]游戏(二分图匹配/并查集)

    题面: https://www.lydsy.com/JudgeOnline/problem.php?id=1854 题解: 1.二分图匹配: 首先我们发现每件装备只能在两种属性中选一种.因此,我们以每 ...

  4. [BZOJ1854][Scoi2010]游戏(二分图匹配/并查集)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1854 分析:很裸的一道二分图匹配对吧,但是在hzwer的blog上看见神奇的并查集做法 ...

  5. HDU 3081:Marriage Match II(二分图匹配+并查集)

    http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也 ...

  6. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

  7. BZOJ.2054.疯狂的馒头(并查集)

    BZOJ 倒序处理,就是并查集傻题了.. 并查集就是确定下一个未染色位置的,直接跳到那个位置染.然而我越想越麻烦=-= 以为有线性的做法,发现还是要并查集.. 数据随机线段树也能过去. //18400 ...

  8. noip 2010 关押罪犯 二分答案+二分图染色 || 并查集

    题目链接 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值&q ...

  9. 2021.08.03 BZOJ 疯狂的馒头(并查集)

    2021.08.03 BZOJ 疯狂的馒头(并查集) 疯狂的馒头 - 题目 - 黑暗爆炸OJ (darkbzoj.tk) 重点: 1.并查集的神奇运用 2.离线化 题意: 给一个长为n的序列,进行m次 ...

随机推荐

  1. printf以及各种变种

    int printf(char *format, [argument]); 其向终端(显示器.控制台等)输出字符 int fprintf(FILE*stream, const char*format, ...

  2. 关于c++中public & private方法调用问题

    class IDNoIdentifier { public: IDNoIdentifier(); ~IDNoIdentifier(); typedef vector<cv::Rect> C ...

  3. solr 学习之数据导入

    将数据库中的数据导入到我们的solr索引库中(DataImportHandler) 1.将jdbc的jar包和solr包中的DataImport的jar包拷贝到webapp中solr/WEB-INF/ ...

  4. C#中整型数据类型

    C#中整型数据类型byte是8位的无符号整数,可是它表示的值的范围是0-255才3位啊怎么说是8位啊?谁能帮我解答 全部答案   八位二进制.0000 0000到1111 1111相当于十进制0-25 ...

  5. 移除 ios 上 input 的默认样式

    input{ -webkit-appearance:none; }

  6. 【POJ2976】Dropping Tests(分数规划)

    [POJ2976]Dropping Tests(分数规划) 题面 Vjudge 翻译在\(Vjudge\)上有(而且很皮) 题解 简单的\(01\)分数规划 需要我们做的是最大化\(\frac{\su ...

  7. BZOJ4299 & CC FRBSUM:ForbiddenSum & BZOJ4408 & 洛谷4587 & LOJ2174:[FJOI2016]神秘数——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4299 https://www.lydsy.com/JudgeOnline/problem.php? ...

  8. cf 443 D. Teams Formation](细节模拟题)

    cf 443 D. Teams Formation(细节模拟题) 题意: 给出一个长为\(n\)的序列,重复\(m\)次形成一个新的序列,动态消除所有k个连续相同的数字,问最后会剩下多少个数(题目保证 ...

  9. BZOJ2006 [NOI2010]超级钢琴 【堆 + RMQ】

    2006: [NOI2010]超级钢琴 Time Limit: 20 Sec  Memory Limit: 552 MB Submit: 3446  Solved: 1692 [Submit][Sta ...

  10. 使用httpclient post请求中文乱码解决办法

    使用httpclient post请求中文乱码解决办法   在使用httpclient发送post请求的时候,接收端中文乱码问题解决. 正文: 我们都知道,一般情况下使用post请求是不会出现中文乱码 ...