题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1515

题目来源: 原创
基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
 收藏
 关注

给n组操作,每组操作形式为x y p。

当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等;否则输出NO,并忽略此次操作。

当p为0时,如果第x变量和第y个变量可以不相等,则输出YES,并限制他们不相等 ;否则输出NO,并忽略此次操作。

Input
输入一个数n表示操作的次数(n<=1*10^5)
接下来n行每行三个数x,y,p(x,y<=1*10^8,p=0 or 1)
Output
对于n行操作,分别输出n行YES或者NO
Input示例
3
1 2 1
1 3 1
2 3 0
Output示例
YES
YES
NO

题解:

1.一开始还以为跟这题POJ2492 A Bug's Life一样,直接种类并查集即可,结果连测试数据都过不了。后来发现:当A!=B, B!=C时,A可能等于C,也可能不等于C,而对于POJ2492,因为元素只有两种,所以A肯定等于C。自己就是受这一题的影响,一直认为A肯定等于C,思想僵化……

2.所以,同一个集合里的元素只能是相等的,即不能用种类并查集了。对此的解决策略是:为每个集合添加一个与之不相等集合的队列。

3.当规定两个集合不相等时,只需各自把对方加入到自己的“不相等”队列即可;当规定两集合相等时,即需要合并两集合,此时,就需要用到启发式合并了:把“不相等”队列小的合并到“不相等”队列大的集合上。

4.启发式合并的时间复杂度为:O(nlogn),证明:每一次把小集合合并到大集合上,则新集合的大小至少为小集合的两倍,即表明每合并一次,集合的大小可翻倍,由于只有n个元素,那么最多只能有logn次翻倍;每一次翻倍,最多只能有n个元素参与,所以时间复杂度为O(nlogn)。

5.在检验两集合是否不相等时,由于还用到了find()函数,所以总体的时间复杂度为:O(n*logn*logn)

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 2e5+; int fa[MAXN];
map<int,int>M; //用于离散化
vector<int>s[MAXN]; //记录与这个变量不相等的变量
int find(int x)
{
return fa[x]==-?x:fa[x]=find(fa[x]);
} bool Union(int u, int v, int w)
{
u = find(u);
v = find(v); if(u==v) //如果在同一个集合,即两变量相等,则直接判断
return (w==);
else //不在同一个集合
{
if(s[u].size()>s[v].size()) swap(u,v);
bool flag = false; //判断两变量是否不相等
int sz = s[u].size();
for(int i = ; i<sz; i++) //用小的集合去判断
{
flag |= find(s[u][i])==v; //s[u][i]可能已经被合并到某个集合,所以要找到其当前所在的集合
if(flag) break; //加上这个判断,不然被卡常数
} if(flag) //不过两变量不相等,则直接判断,并返回
return (w==);
else if(w==) //否则,如果要求两变量相等,则两者所在的集合
{
fa[u] = v;
sz = s[u].size();
for(int i = ; i<sz; i++) //启发式合并的关键
s[v].push_back(s[u][i]);
s[u].clear();
}
else //如果要求两变量不相等,则各自把对方加入到自己的“不相等”队列
{
s[u].push_back(v);
s[v].push_back(u);
}
}
return true;
} int main()
{
int n, m;
while(scanf("%d",&n)!=EOF)
{
M.clear();
m = ;
memset(fa,-,sizeof(fa));
for(int i = ; i<MAXN; i++)
s[i].clear();
for(int i = ; i<=n; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(M.find(u)==M.end()) M[u] = ++m;
if(M.find(v)==M.end()) M[v] = ++m; if(Union(M[u],M[v],!w)) puts("YES");
else puts("NO");
}
}
}

51Nod 1515 明辨是非 —— 并查集 + 启发式合并的更多相关文章

  1. 51nod 1515 明辨是非 [并查集+set]

    今天cb巨巨突然拿题来问,感觉惊讶又开心,希望他早日康复!!坚持学acm!加油! 题目链接:51nod 1515 明辨是非 [并查集] 1515 明辨是非 题目来源: 原创 基准时间限制:1 秒 空间 ...

  2. 51nod 1515 明辨是非 并查集+set维护相等与不等关系

    考试时先拿vector瞎搞不等信息,又没离散化,结果好像MLE:后来想起课上讲过用set维护,就开始瞎搞迭代器...QWQ我太菜了.. 用并查集维护相等信息,用set记录不相等的信息: 如果要求变量不 ...

  3. 51nod 1515 明辨是非 并查集 + set + 启发式合并

    给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等:否则输出NO,并忽略此次操作. 当p为0时,如果第x变量和第y个变量可以不相等,则输 ...

  4. BZOJ2733[HNOI2012]永无乡——线段树合并+并查集+启发式合并

    题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...

  5. BZOJ 4668: 冷战 并查集启发式合并/LCT

    挺好想的,最简单的方法是并查集启发式合并,加暴力跳父亲. 然而,这个代码量比较小,比较好写,所以我写了 LCT,更具挑战性. #include <cstdio> #include < ...

  6. [HDU 3712] Fiolki (带边权并查集+启发式合并)

    [HDU 3712] Fiolki (带边权并查集+启发式合并) 题面 化学家吉丽想要配置一种神奇的药水来拯救世界. 吉丽有n种不同的液体物质,和n个药瓶(均从1到n编号).初始时,第i个瓶内装着g[ ...

  7. [BZOJ 4668]冷战(带边权并查集+启发式合并)

    [BZOJ 4668]冷战(并查集+启发式合并) 题面 一开始有n个点,动态加边,同时查询u,v最早什么时候联通.强制在线 分析 用并查集维护连通性,每个点x还要另外记录tim[x],表示x什么时间与 ...

  8. 51 nod 1515 明辨是非(并查集合并)

    1515 明辨是非题目来源: 原创基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以 ...

  9. BZOJ 3673: 可持久化并查集(可持久化并查集+启发式合并)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3673 题意: 思路: 可持久化数组可以用可持久化线段树来实现,并查集的查询操作和原来的一般并查集操作 ...

随机推荐

  1. GTD实用指南

    以前通过余弦大牛博客接触到了GTD, 后来我自己接触之后呢, 我是非常讨厌GTD的, 因为太功利化了 反人类 我还是比较懒得··· 可是最近事情真的比较多,不得不做GTD了 = =  郁闷! 时间管理 ...

  2. bat文件转换为exe文件

    批处理文件转换为exe文件(简单的处理文件),点击下载 使用超简单的了,不多说.

  3. hql小经验

    hql如果查了子对象的属性,那么hql不允许子对象为空!

  4. DIV旋转的測试代码

    <html> <head> <style type="text/css"> .rat0 { -webkit-transform: rotate( ...

  5. 【Excle】Excle中的逆向查询

    一般vlookup使用 一般的vlookup使用,想必都会了,下面是一个一般vlookup的例子 意思就是以F2为查询值,区域A2:D10为查找区域,在首列中找到与F2单元格相同的工号,然后返回这个区 ...

  6. 搭建SpringMVC+Hibernate4+Spring3+Ajax+Maven项目

    首先新建一个Maven项目.百度一下会有非常多实例,这里就不介绍了,直接奔主题. 如题:这里使用的是Hibernate4和Spring3,使用的JPA和Spring注解,然后JDK版本号是1.7 以下 ...

  7. iOS中 扫描二维码/生成二维码具体解释 韩俊强的博客

    近期大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 指示根视图: se ...

  8. Linux内核编译过程分析

    http://pan.baidu.com/s/1mgtACVu 其中是我总结生成的一些文档,以便于理解当我们输入make uImage后,系统是怎么一步一步生成uImage的,我采用的是逆向分析的方法 ...

  9. Docker入门系列4:命令行小结

    百度Baidu App Engine(BAE)平台也是以Docker作为其PaaS云基础. 目的就是为了解决以下问题: 1) 环境管理复杂: 从各种OS到各种中间件再到各种App,一款产品能够成功发布 ...

  10. Java知识点梳理——泛型

    1.定义:泛型的本质是参数化类型,就是将类型由原来的具体的类型参数化,这种参数类型可以用在类.接口.方法中,分别称为泛型类.泛型接口.泛型方法: 2.泛型类:泛型类的声明和非泛型类的声明类似,除了在类 ...