51nod 1515 明辨是非 并查集 + set + 启发式合并
2016-09-17 11:07
369 查看
给n组操作,每组操作形式为x y p。
当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等;否则输出NO,并忽略此次操作。
当p为0时,如果第x变量和第y个变量可以不相等,则输出YES,并限制他们不相等 ;否则输出NO,并忽略此次操作。
Input
Output
Input示例
Output示例
当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,放着所有确定了和这个 集合不相等的集合的父节点,然后合并的时候启发式合并一下。 代码:
//File Name: nod1515.cpp //Author: long //Mail: 736726758@qq.com //Created Time: 2016年09月16日 星期五 23时01分02秒 #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <set> #include <map> using namespace std; const int MAXN = 100000 + 10; int fa[MAXN]; map<int,int> rem; set<int> dis[MAXN]; struct Query{ int x,y,p; }que[MAXN]; int find_fa(int x){ if(fa[x] == x) return x; return fa[x] = find_fa(fa[x]); } void union_to(int x,int y){ fa[y] = x; set<int>::iterator it; for(it=dis[y].begin();it!=dis[y].end();it++){ int v = *it; dis[v].erase(y); dis[v].insert(x); dis[x].insert(v); } dis[y].clear(); } void _union(int x,int y){ if(dis[x].size() >= dis[y].size()) union_to(x,y); else union_to(y,x); } void solve(int n,int tot){ for(int i=1;i<=n;i++){ que[i].x = rem[que[i].x]; que[i].y = rem[que[i].y]; } for(int i=1;i<=tot;i++){ fa[i] = i; dis[i].clear(); } for(int i=1;i<=n;i++){ int x = que[i].x,y = que[i].y,p = que[i].p; int fax = find_fa(x); int fay = find_fa(y); if(fax == fay){ if(p) puts("YES"); else puts("NO"); } else{ if(p){ if(dis[fax].find(fay) != dis[fax].end()) puts("NO"); else{ puts("YES"); _union(fax,fay); } } else{ puts("YES"); dis[fax].insert(fay); dis[fay].insert(fax); } } } } int main(){ int n; while(~scanf("%d",&n)){ int tot = 0; rem.clear(); for(int i=1;i<=n;i++){ scanf("%d %d %d",&que[i].x,&que[i].y,&que[i].p); if(!rem[que[i].x]) rem[que[i].x] = ++tot; if(!rem[que[i].y]) rem[que[i].y] = ++tot; } solve(n,tot); } return 0; }
相关文章推荐
- 51nod 1515 明辨是非[并查集][set]
- 51nod 1515:明辨是非 并查集合并
- 51nod 1515:明辨是非 并查集合并
- 51nod 1515 明辨是非 启发式合并
- 51nod 1515 明辨是非(合并并查集)
- 51 nod 1515 明辨是非(并查集合并)
- CDOJ1927 爱吃瓜的伊卡洛斯(2) 【并查集】启发式合并+set
- [后缀数组][trie合并][启发式合并][并查集] LOJ #6198. 谢特
- hiho 1561 观光旅行 [set启发式合并+想法]
- 【[Offer收割]编程练习赛23 D】【最小生成树+set的启发式合并】观光旅行
- 可持久化并查集(外传)——[按秩启发式合并]
- 【51nod 1515】 明辨是非
- [并查集][排序][dfs][启发式合并] JZOJ P3635 Peaks
- 51nod 1515 明辨是非 && 2017百度之星初赛第一场第二题(并查集+启发式合并)
- 【51Nod 1515】明辨是非
- CodeForces 932F Escape Through Leaf [set启发式合并+维护凸包+二分]
- POJ 1611 The Suspects 并查集(代码带启发式合并)
- UOJ356 [JOI2017春季合宿] Port Facility 【启发式合并】【堆】【并查集】
- 【CF932F】Escape Through Leaf 启发式合并set维护凸包
- 并查集的启发式合并 和 路径压缩