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

Posted c

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
2 3 0
Output示例
YES
YES
NO


刚开始只是用了一个并查集,维护每一个节点和其父节点的关系,相等或者不相等,
但是这样是不对的,比如a != b,c != b,但是这个时候a和c 的关系不能确定。
改为:
用并查集维护相等的关系,每一个并查集的父节点再维护一个set,放着所有确定了和这个
集合不相等的集合的父节点,然后合并的时候启发式合并一下。

代码:
 1                                             
 2   //File Name: nod1515.cpp
 3   //Author: long
 4   //Mail: [email protected]
 5   //Created Time: 2016年09月16日 星期五 23时01分02秒
 6                                    
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <algorithm>
10 #include <iostream>
11 #include <set>
12 #include <map>
13 using namespace std;
14 const int MAXN = 100000 + 10;
15 int fa[MAXN];
16 map<int,int> rem;
17 set<int> dis[MAXN];
18 struct Query{
19     int x,y,p;
20 }que[MAXN];
21 int find_fa(int x){
22     if(fa[x] == x) return x;
23     return fa[x] = find_fa(fa[x]);
24 }
25 void union_to(int x,int y){
26     fa[y] = x;
27     set<int>::iterator it;
28     for(it=dis[y].begin();it!=dis[y].end();it++){
29         int v = *it;
30         dis[v].erase(y);
31         dis[v].insert(x);
32         dis[x].insert(v);
33     }
34     dis[y].clear();
35 }
36 void _union(int x,int y){
37     if(dis[x].size() >= dis[y].size()) union_to(x,y);
38     else union_to(y,x);
39 }
40 void solve(int n,int tot){
41     for(int i=1;i<=n;i++){
42         que[i].x = rem[que[i].x];
43         que[i].y = rem[que[i].y];
44     }
45     for(int i=1;i<=tot;i++){
46         fa[i] = i;
47         dis[i].clear();
48     }
49     for(int i=1;i<=n;i++){
50         int x = que[i].x,y = que[i].y,p = que[i].p;
51         int fax = find_fa(x);
52         int fay = find_fa(y);
53         if(fax == fay){
54             if(p) puts("YES");
55             else puts("NO");
56         }
57         else{
58             if(p){
59                 if(dis[fax].find(fay) != dis[fax].end()) puts("NO");
60                 else{
61                     puts("YES");
62                     _union(fax,fay);
63                 }
64             }
65             else{
66                 puts("YES");
67                 dis[fax].insert(fay);
68                 dis[fay].insert(fax);
69             }
70         }
71     }
72 }
73 int main(){
74     int n;
75     while(~scanf("%d",&n)){
76         int tot = 0;
77         rem.clear();
78         for(int i=1;i<=n;i++){
79             scanf("%d %d %d",&que[i].x,&que[i].y,&que[i].p);
80             if(!rem[que[i].x]) rem[que[i].x] = ++tot;
81             if(!rem[que[i].y]) rem[que[i].y] = ++tot;
82         }
83         solve(n,tot);
84     }
85     return 0;
86 }

 





以上是关于51nod 1515 明辨是非 并查集 + set + 启发式合并的主要内容,如果未能解决你的问题,请参考以下文章

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

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

[題解]51nod_1515_明辨是非

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

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

[51nod1515]明辨是非