题目链接

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. Log-spectral distance

    Log-spectral distance对数频谱距离 log-spectral distance(LSD),也指 log-spectral distortion,是两个频谱之间的距离度量(用分贝表示 ...

  2. MATLAN中矩阵表示中有一维是~表示的意思

    [~,m]表示的意思解释. [~,m]=rat(12/34) m = 17 >> [x,m]=rat(12/34) x = 6 m = 17

  3. 【题解】CQOI2012局部最小值

    上课讲的一道题,感觉也挺厉害的~正解是容斥 + 状压dp.首先我们容易发现一共可能的局部最小值数量是十分有限的,最多也只有 \(8\) 个.所以我们可以考虑状压. 建立出状态 \(f[i][j]\) ...

  4. bzoj 2140: 稳定婚姻 (二分图)

    //========================== 蒟蒻Macaulish:http://www.cnblogs.com/Macaulish/  转载要声明! //=============== ...

  5. NOIP 2018 -The Wound-

    "一招不慎,满盘皆输" 如果这个盘是整整一年的OI生涯的话 那么"一招"一定就是NOIP了 Update 2019/4/6 剧变的一年 noip这个成绩意味着我 ...

  6. HDOJ.2094 产生冠军(map)

    产生冠军 点我挑战题目 点我一起学习STL-MAP 题意分析 给出n组数据,代表a打败了b,让判断根据这n组数据是否能判断出来产生了冠军.一开始以为这道题很难,其实用map可以应付. 大原则,赢了的人 ...

  7. UVA.1584 环状序列

    UVA.1584 环状序列 点我看题面 题意分析 给出你一段换装DNA序列,然后让你输出这段环状序列的字典序最小的序列情况. 字典序字面意思上理解就是按照字典编排的序列,其实也可以理解为按照ASCII ...

  8. GCJ2008 APAC local onsites C Millionaire

    自己Blog的第一篇文章,嗯... 接触这道题,是从<挑战程序设计竞赛>这本书看来的,其实头一遍读题解,并没有懂.当然现在已经理解了,想想当初可能是因为考虑两轮的那张概率图的问题.于是决定 ...

  9. 谈谈Javascript的匿名函数

    JQuery 里面有这么一种代码: (function(){ // code here })(); 当一个匿名函数被括起来,然后再在后面加一个括号,这个匿名函数就能立即运行起来,神奇吧! 要说匿名函数 ...

  10. PowerDesigner 技巧【1】

    Name与Code同步的问题: PowerDesigner中,修改了某个字段的name,其code也跟着修改,这个问题很讨厌,因为一般来说,name是中文的,code是字段名. 解决方法如下: 1.选 ...