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 + 启发式合并的主要内容,如果未能解决你的问题,请参考以下文章