51nod-1515 明辨是非——并查集

给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

这题目描述实在是很迷,看了半天才明白,一共三种关系,相等,不相等和不确定,只有YES操作会改变不确定关系。用set来维护限制不相等的数,用并查集维护限制相等的数,两个数从不确定到不相等,互相插入对方的set;两个数从不确定到相等,改变他们的父结点,默认将小的那个集合的父结点改成大的,就是大吃小的意思。
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <set>
 4 #include <map>
 5
 6 using namespace std;
 7
 8 const int MAXN = 2e5 + 5;
 9
10 int n, cnt = 1,f[MAXN];
11 set<int> nt[MAXN];
12 map<int, int> eq;
13
14 int find(int x)
15 {
16     return f[x] == x ? x : f[x] = find(f[x]);
17 }
18
19 int main()
20 {
21     //freopen("in.txt","r",stdin);
22     cin>>n;
23     n +=5;
24     for (int i = 1; i <= n; i++)
25     {
26         f[i] = i;
27     }
28     n -=5;
29
30     int x, y, p;
31     while (n--)
32     {
33         cin>>x>>y>>p;
34         if (eq[x])//计数标号
35         {
36             x = eq[x];
37         }
38         else
39         {
40             ++cnt;
41             eq[x]=cnt;
42             x=cnt;
43         }
44         if (eq[y])
45         {
46             y = eq[y];
47         }
48         else
49         {
50             ++cnt;
51             eq[y]=cnt;
52             y=cnt;
53         }
54         int u = find(x), v = find(y);
55         if (p == 1)//限制相等
56         {
57             if (nt[u].count(v)) //限制不相等
58             {
59                 cout<<"NO"<<endl;
60             }
61             else if (u != v)    //未限制但并未相等
62             {
63                 if (nt[u].size() > nt[v].size())
64                 {
65                     swap(u, v);
66                 }
67                 f[u] = v;
68                 set<int>::iterator it;
69                 for (it = nt[u].begin(); it != nt[u].end(); it++)
70                 {
71                     nt[*it].insert(v);
72                     nt[v].insert(*it);
73                 }
74                 cout<<"YES"<<endl;
75             }
76             else
77             {
78                 cout<<"YES"<<endl;
79             }
80         }
81         else//限制不相等
82         {
83             if (u == v)
84             {
85                 cout<<"NO"<<endl;
86             }
87             else
88             {
89                 nt[u].insert(v);
90                 nt[v].insert(u);
91                 cout<<"YES"<<endl;
92             }
93         }
94     }
95
96     return 0;
97 }

原文地址:https://www.cnblogs.com/fantastic123/p/8947335.html

时间: 2024-10-30 01:19:35

51nod-1515 明辨是非——并查集的相关文章

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

今天cb巨巨突然拿题来问,感觉惊讶又开心,希望他早日康复!!坚持学acm!加油! 这题一看感觉我写不出来orz, 就晚睡一点也要把WA的代码改AC!! 好困啊,直接贴了睡觉.zZ 题目链接:51nod 1515 明辨是非 [并查集] 1515 明辨是非 题目来源: 原创 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 给n组操作,每组操作形式为x y p. 当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等:否则输出NO,并忽略此次操

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

给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

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

考试时先拿vector瞎搞不等信息,又没离散化,结果好像MLE:后来想起课上讲过用set维护,就开始瞎搞迭代器...QWQ我太菜了.. 用并查集维护相等信息,用set记录不相等的信息: 如果要求变量不等,若不和并查集矛盾,就拿set互相记录一下,YES:矛盾就NO 如果要求变量相等, 1.x记录的不等的变量中有y,说明矛盾,NO 2.若祖先不等,那就合并两个变量所在的并查集(合并两个并查集的祖先),size大的并到小的上,set暴力转移集合不相等的信息,YES 否则YES #include<cs

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

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

51Nod 1515(并查集、set、离散化)

//代码还是YY学姐帮改的,自己从来没有真正A过几道题,不是看题解就是有BUG找不出,多久了还是改变不了这样的现状,或许ACM就是这么筛选人的吧.从5.24到11.24,再到又一年的5.24,可感觉后者比前者过得快多了.多读了一年的大学,完全没有了时间概念,不知道现在到底是大几了,不知道现在到底处在什么位置,不知道毕业后到底从不从事IT这行,一切都是未知的. 题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=15

51nod 1204 Parity(并查集应用)

1204 Parity 题目来源: Ural 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 你的朋友写下一串包含1和0的串让你猜,你可以从中选择一个连续的子串(例如其中的第3到第5个数字)问他,该子串中包含了奇数个还是偶数个1,他会回答你的问题,然后你可以继续提问......你怀疑朋友的答案可能有错,或说同他之前的答案相互矛盾,例如:1 - 2 奇数,3 - 4 奇数,那么可以确定1 - 4 一定是偶数,如果你的朋友回答是奇数,就产生了矛盾.给出所有你朋友的

51nod 1307 绳子与重物(并查集水了一发)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 题意: 思路: 可以直接二分答案,然后dfs. 因为标签是并查集,所以我考虑了一下并查集,利用并查集不断向上回溯加负重,居然过了,只能说数据有点水. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #incl

hihoCoder 1515 分数调查(带权并查集)

http://hihocoder.com/problemset/problem/1515 题意: 思路: 带权并查集的简单题,计算的时候利用向量法则即可. 1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn = 100000+5; 5 6 int n,m,q; 7 int p[maxn],r[maxn]; 8 9 int finds(int x) 10 { 11 if(p[x

带权并查集(含种类并查集)【经典模板】 例题:①POJ 1182 食物链(经典)②HDU - 1829 A bug&#39;s life(简单) ③hihoCoder 1515 : 分数调查

带权并查集: 增加一个 value 值,并且每次合并和查找的时候需要去维护这个 value 例题一 :POJ 1182 食物链(经典) 题目链接:https://vjudge.net/contest/339425#problem/E 带权并查集的解法 定义两个数组fa[ ]和rela[ ],fa用来判断集合关系,rela用来描述其与根节点的关系.因为关系满足传递性,所以可以推导出给出条件下的当前关系,在判断与之前已有关系是否矛盾. 本题的解法巧妙地利用了模运算,rela数组用0表示同类,1表示当